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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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 efbacb97c9d57a449a45da2110b550303e0a0398 Mon Sep 17 00:00:00 2001 From: mihailik Date: Mon, 9 Nov 2015 09:45:57 +0000 Subject: [PATCH 15/93] Use ts.indexOf instead of Array.prototype.indexOf (keep consistent with the rest of codebase, and thus enable ES3-compatibility of tsc and services) --- 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 706ed1c65a3..c4a60cd3355 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3731,7 +3731,7 @@ namespace ts { if (node.initializer) { const signatureDeclaration = node.parent; const signature = getSignatureFromDeclaration(signatureDeclaration); - const parameterIndex = signatureDeclaration.parameters.indexOf(node); + const parameterIndex = ts.indexOf(signatureDeclaration.parameters, node); Debug.assert(parameterIndex >= 0); return parameterIndex >= signature.minArgumentCount; } From 4ca24bf1318d26b0770275417cf2e634a8ad5049 Mon Sep 17 00:00:00 2001 From: mihailik Date: Mon, 9 Nov 2015 09:52:13 +0000 Subject: [PATCH 16/93] Use ts.indexOf instead of Array.prototype.indexOf (keep consistent with the rest of codebase, and thus enable ES3-compatibility of tsc and services) --- src/services/formatting/tokenRange.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/formatting/tokenRange.ts b/src/services/formatting/tokenRange.ts index 19185cdf78d..1afde613618 100644 --- a/src/services/formatting/tokenRange.ts +++ b/src/services/formatting/tokenRange.ts @@ -14,7 +14,7 @@ namespace ts.formatting { constructor(from: SyntaxKind, to: SyntaxKind, except: SyntaxKind[]) { this.tokens = []; for (let token = from; token <= to; token++) { - if (except.indexOf(token) < 0) { + if (ts.indexOf(except, token) < 0) { this.tokens.push(token); } } @@ -123,4 +123,4 @@ namespace ts.formatting { static TypeNames = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.NumberKeyword, SyntaxKind.StringKeyword, SyntaxKind.BooleanKeyword, SyntaxKind.SymbolKeyword, SyntaxKind.VoidKeyword, SyntaxKind.AnyKeyword]); } } -} \ No newline at end of file +} From cfc6ed2adb4bc51f0eac52060a2ccc0d57a3e951 Mon Sep 17 00:00:00 2001 From: Basarat Syed Date: Tue, 10 Nov 2015 18:33:19 +1100 Subject: [PATCH 17/93] tsx : support tags in language service semantic tokenizer --- src/services/services.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/services/services.ts b/src/services/services.ts index 113a52459e9..ad8481e82cb 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1611,6 +1611,9 @@ namespace ts { public static typeAliasName = "type alias name"; public static parameterName = "parameter name"; public static docCommentTagName = "doc comment tag name"; + public static jsxOpenTagName = "jsx open tag name"; + public static jsxCloseTagName = "jsx close tag name"; + public static jsxSelfClosingTagName = "jsx self closing tag name"; } export const enum ClassificationType { @@ -1632,6 +1635,9 @@ namespace ts { typeAliasName = 16, parameterName = 17, docCommentTagName = 18, + jsxOpenTagName = 19, + jsxCloseTagName = 20, + jsxSelfClosingTagName = 21, } /// Language Service @@ -6619,6 +6625,9 @@ namespace ts { case ClassificationType.typeAliasName: return ClassificationTypeNames.typeAliasName; case ClassificationType.parameterName: return ClassificationTypeNames.parameterName; case ClassificationType.docCommentTagName: return ClassificationTypeNames.docCommentTagName; + case ClassificationType.jsxOpenTagName: return ClassificationTypeNames.jsxOpenTagName; + case ClassificationType.jsxCloseTagName: return ClassificationTypeNames.jsxCloseTagName; + case ClassificationType.jsxSelfClosingTagName: return ClassificationTypeNames.jsxSelfClosingTagName; } } @@ -6931,6 +6940,23 @@ namespace ts { } return; + case SyntaxKind.JsxOpeningElement: + if ((token.parent).tagName === token) { + return ClassificationType.jsxOpenTagName; + } + return; + + case SyntaxKind.JsxClosingElement: + if ((token.parent).tagName === token) { + return ClassificationType.jsxCloseTagName; + } + return; + + case SyntaxKind.JsxSelfClosingElement: + if ((token.parent).tagName === token) { + return ClassificationType.jsxSelfClosingTagName; + } + return; } } From 48e985d72f12af17d39b47140491a8b52ccb29df Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 10 Nov 2015 11:35:03 -0800 Subject: [PATCH 18/93] Prevent resolveName from ignoring default exports --- src/compiler/checker.ts | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 706ed1c65a3..05ced970793 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -487,8 +487,9 @@ namespace ts { (location.kind === SyntaxKind.ModuleDeclaration && (location).name.kind === SyntaxKind.StringLiteral)) { // It's an external module. Because of module/namespace merging, a module's exports are in scope, - // yet we never want to treat an export specifier as putting a member in scope. Therefore, - // if the name we find is purely an export specifier, it is not actually considered in scope. + // yet we never want to treat an export specifier as putting a member in scope, except 'default'. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope, + // unless it is 'default'. // Two things to note about this: // 1. We have to check this without calling getSymbol. The problem with calling getSymbol // on an export specifier is that it might find the export specifier itself, and try to @@ -497,15 +498,16 @@ namespace ts { // 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely* // an alias. If we used &, we'd be throwing out symbols that have non alias aspects, // which is not the desired behavior. + const isLocalSymbolForExportDefault = doesNameResolveToLocalSymbolForExportDefault(moduleExports, meaning, name); if (hasProperty(moduleExports, name) && moduleExports[name].flags === SymbolFlags.Alias && + !isLocalSymbolForExportDefault && getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) { break; } - result = moduleExports["default"]; - const localSymbol = getLocalSymbolForExportDefault(result); - if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) { + if (isLocalSymbolForExportDefault) { + result = moduleExports["default"]; break loop; } result = undefined; @@ -674,6 +676,12 @@ namespace ts { return result; } + function doesNameResolveToLocalSymbolForExportDefault(exports: SymbolTable, meaning: SymbolFlags, name: string): boolean { + const defaultExport = exports["default"]; + const localSymbol = getLocalSymbolForExportDefault(defaultExport); + return defaultExport && (defaultExport.flags & meaning) && localSymbol && localSymbol.name === name; + } + function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); // Block-scoped variables cannot be used before their definition @@ -4124,12 +4132,12 @@ namespace ts { // We only support expressions that are simple qualified names. For other expressions this produces undefined. const typeNameOrExpression = node.kind === SyntaxKind.TypeReference ? (node).typeName : isSupportedExpressionWithTypeArguments(node) ? (node).expression : - undefined; + undefined; const symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol; const type = symbol === unknownSymbol ? unknownType : symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) : - symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) : - getTypeFromNonGenericTypeReference(node, symbol); + symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) : + getTypeFromNonGenericTypeReference(node, symbol); // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the // type reference in checkTypeReferenceOrExpressionWithTypeArguments. links.resolvedSymbol = symbol; @@ -11309,7 +11317,7 @@ namespace ts { // Abstract methods can't have an implementation -- in particular, they don't need one. if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) { + !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } @@ -14221,8 +14229,8 @@ namespace ts { if (className) { copySymbol(location.symbol, meaning); } - // fall through; this fall-through is necessary because we would like to handle - // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration + // fall through; this fall-through is necessary because we would like to handle + // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: // If we didn't come from static member of class or interface, @@ -14378,8 +14386,8 @@ namespace ts { return resolveEntityName(entityName, meaning); } else if ((entityName.parent.kind === SyntaxKind.JsxOpeningElement) || - (entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) || - (entityName.parent.kind === SyntaxKind.JsxClosingElement)) { + (entityName.parent.kind === SyntaxKind.JsxSelfClosingElement) || + (entityName.parent.kind === SyntaxKind.JsxClosingElement)) { return getJsxElementTagSymbol(entityName.parent); } else if (isExpression(entityName)) { @@ -14446,8 +14454,8 @@ namespace ts { : getSymbolOfPartOfRightHandSideOfImportEquals(node); } else if (node.parent.kind === SyntaxKind.BindingElement && - node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && - node === (node.parent).propertyName) { + node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && + node === (node.parent).propertyName) { const typeOfPattern = getTypeOfNode(node.parent.parent); const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (node).text); @@ -14484,7 +14492,7 @@ namespace ts { (node.parent).moduleSpecifier === node)) { return resolveExternalModuleName(node, node); } - // Fall through + // Fall through case SyntaxKind.NumericLiteral: // index access @@ -14680,7 +14688,7 @@ namespace ts { if (links.isNestedRedeclaration === undefined) { const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); links.isNestedRedeclaration = isStatementWithLocals(container) && - !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); + !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); } return links.isNestedRedeclaration; } From e30a01db0fb06dc93177f194cfd919ca4d4baec3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 10 Nov 2015 11:44:56 -0800 Subject: [PATCH 19/93] Add test case and accept baseline --- .../reference/reExportDefaultExport.js | 27 +++++++++++++++++++ .../reference/reExportDefaultExport.symbols | 22 +++++++++++++++ .../reference/reExportDefaultExport.types | 24 +++++++++++++++++ .../es6/modules/reExportDefaultExport.ts | 15 +++++++++++ 4 files changed, 88 insertions(+) create mode 100644 tests/baselines/reference/reExportDefaultExport.js create mode 100644 tests/baselines/reference/reExportDefaultExport.symbols create mode 100644 tests/baselines/reference/reExportDefaultExport.types create mode 100644 tests/cases/conformance/es6/modules/reExportDefaultExport.ts diff --git a/tests/baselines/reference/reExportDefaultExport.js b/tests/baselines/reference/reExportDefaultExport.js new file mode 100644 index 00000000000..dbe3dfdbbae --- /dev/null +++ b/tests/baselines/reference/reExportDefaultExport.js @@ -0,0 +1,27 @@ +//// [tests/cases/conformance/es6/modules/reExportDefaultExport.ts] //// + +//// [m1.ts] + +export default function f() { +} +export {f}; + + +//// [m2.ts] +import foo from "./m1"; +import {f} from "./m1"; + +f(); +foo(); + +//// [m1.js] +function f() { +} +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = f; +exports.f = f; +//// [m2.js] +var m1_1 = require("./m1"); +var m1_2 = require("./m1"); +m1_2.f(); +m1_1.default(); diff --git a/tests/baselines/reference/reExportDefaultExport.symbols b/tests/baselines/reference/reExportDefaultExport.symbols new file mode 100644 index 00000000000..cd0d6e493c9 --- /dev/null +++ b/tests/baselines/reference/reExportDefaultExport.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/es6/modules/m1.ts === + +export default function f() { +>f : Symbol(f, Decl(m1.ts, 0, 0)) +} +export {f}; +>f : Symbol(f, Decl(m1.ts, 3, 8)) + + +=== tests/cases/conformance/es6/modules/m2.ts === +import foo from "./m1"; +>foo : Symbol(foo, Decl(m2.ts, 0, 6)) + +import {f} from "./m1"; +>f : Symbol(f, Decl(m2.ts, 1, 8)) + +f(); +>f : Symbol(f, Decl(m2.ts, 1, 8)) + +foo(); +>foo : Symbol(foo, Decl(m2.ts, 0, 6)) + diff --git a/tests/baselines/reference/reExportDefaultExport.types b/tests/baselines/reference/reExportDefaultExport.types new file mode 100644 index 00000000000..f775571ac2c --- /dev/null +++ b/tests/baselines/reference/reExportDefaultExport.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/es6/modules/m1.ts === + +export default function f() { +>f : () => void +} +export {f}; +>f : () => void + + +=== tests/cases/conformance/es6/modules/m2.ts === +import foo from "./m1"; +>foo : () => void + +import {f} from "./m1"; +>f : () => void + +f(); +>f() : void +>f : () => void + +foo(); +>foo() : void +>foo : () => void + diff --git a/tests/cases/conformance/es6/modules/reExportDefaultExport.ts b/tests/cases/conformance/es6/modules/reExportDefaultExport.ts new file mode 100644 index 00000000000..730435fd4ee --- /dev/null +++ b/tests/cases/conformance/es6/modules/reExportDefaultExport.ts @@ -0,0 +1,15 @@ +// @module: commonjs +// @target: ES5 + +// @filename: m1.ts +export default function f() { +} +export {f}; + + +// @filename: m2.ts +import foo from "./m1"; +import {f} from "./m1"; + +f(); +foo(); \ No newline at end of file From 694c714cf594f714ca87069021a94d7d8dd75cb4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 11:56:32 -0800 Subject: [PATCH 20/93] Added test for parenthesized string literals. --- .../stringLiteralTypesAndParenthesizedExpressions01.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts new file mode 100644 index 00000000000..7910c0e16b7 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts @@ -0,0 +1,8 @@ +// @declaration: true + +declare function myRandBool(): boolean; + +let a: "foo" = ("foo"); +let b: "foo" | "bar" = ("foo"); +let c: "foo" = (myRandBool ? "foo" : ("foo")); +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); From 6dcf3cf75696d79a7f422ab8a7f423bc36352aed Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 12:06:25 -0800 Subject: [PATCH 21/93] Add case sensitivity-check, only error on failure when outDir is specified and resource based paths are found --- src/compiler/program.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8f031a4de43..aee66834a11 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -888,7 +888,7 @@ namespace ts { function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string { let commonPathComponents: string[]; - forEach(files, sourceFile => { + const failed = forEach(files, sourceFile => { // Each file contributes into common source file path if (isDeclarationFile(sourceFile)) { return; @@ -903,11 +903,12 @@ namespace ts { return; } + const caseSensitive = host.useCaseSensitiveFileNames(); for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (caseSensitive ? commonPathComponents[i] !== sourcePathComponents[i] : commonPathComponents[i].toLocaleLowerCase() !== sourcePathComponents[i].toLocaleLowerCase()) { if (i === 0) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - return; + // Failed to find any common path component + return true; } // New common path found that is 0 -> i-1 @@ -922,6 +923,11 @@ namespace ts { } }); + // A common path can not be found when paths span multiple drives on windows, for example + if (failed) { + return ""; + } + if (!commonPathComponents) { // Can happen when all input files are .d.ts files return currentDirectory; } @@ -1045,6 +1051,10 @@ namespace ts { else { // Compute the commonSourceDirectory from the input files commonSourceDirectory = computeCommonSourceDirectory(files); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure + if (options.outDir && commonSourceDirectory === "" && forEach(files, file => getRootLength(file.fileName) > 1)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); + } } if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) { From abc230195c5d708015383967a27a4aaed2872872 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 12:12:14 -0800 Subject: [PATCH 22/93] Add handling for json parse errors --- src/compiler/tsc.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 79158cf4e9d..474d7212070 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -349,6 +349,11 @@ namespace ts { const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText); const configObject = result.config; + if (!configObject) { + reportDiagnostics([result.error], /* compilerHost */ undefined); + sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } const configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName)); if (configParseResult.errors.length > 0) { reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); From 38127457372b917d49d8c5ee9955ac8e1d88db42 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 12:59:39 -0800 Subject: [PATCH 23/93] Added other tests for string literal types. --- .../stringLiteralTypesAndLogicalOrExpressions01.ts | 9 +++++++++ .../types/stringLiteral/stringLiteralTypesOverloads04.ts | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts new file mode 100644 index 00000000000..8a257ae1caf --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts @@ -0,0 +1,9 @@ +// @declaration: true + +declare function myRandBool(): boolean; + +let a: "foo" = "foo"; +let b = a || "foo"; +let c: "foo" = b; +let d = b || "bar"; +let e: "foo" | "bar" = d; diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts new file mode 100644 index 00000000000..8bc2a0c94b8 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts @@ -0,0 +1,8 @@ +// @declaration: true + +declare function f(x: (p: "foo" | "bar") => "foo"); + +f(y => { + let z = y = "foo"; + return z; +}) \ No newline at end of file From f80a6c6e869b9f84bee99bdfd20594423f56d263 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 11:56:50 -0800 Subject: [PATCH 24/93] Accepted baselines. --- ...ngLiteralTypesAndLogicalOrExpressions01.js | 26 +++++++++++++++++ ...eralTypesAndLogicalOrExpressions01.symbols | 24 +++++++++++++++ ...iteralTypesAndLogicalOrExpressions01.types | 29 +++++++++++++++++++ ...esAndParenthesizedExpressions01.errors.txt | 17 +++++++++++ ...teralTypesAndParenthesizedExpressions01.js | 23 +++++++++++++++ .../stringLiteralTypesOverloads04.js | 18 ++++++++++++ .../stringLiteralTypesOverloads04.symbols | 19 ++++++++++++ .../stringLiteralTypesOverloads04.types | 23 +++++++++++++++ 8 files changed, 179 insertions(+) create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.js create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads04.types diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js new file mode 100644 index 00000000000..479256b18b7 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js @@ -0,0 +1,26 @@ +//// [stringLiteralTypesAndLogicalOrExpressions01.ts] + +declare function myRandBool(): boolean; + +let a: "foo" = "foo"; +let b = a || "foo"; +let c: "foo" = b; +let d = b || "bar"; +let e: "foo" | "bar" = d; + + +//// [stringLiteralTypesAndLogicalOrExpressions01.js] +var a = "foo"; +var b = a || "foo"; +var c = b; +var d = b || "bar"; +var e = d; + + +//// [stringLiteralTypesAndLogicalOrExpressions01.d.ts] +declare function myRandBool(): boolean; +declare let a: "foo"; +declare let b: "foo"; +declare let c: "foo"; +declare let d: "foo" | "bar"; +declare let e: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols new file mode 100644 index 00000000000..2a9f28e85a5 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 0, 0)) + +let a: "foo" = "foo"; +>a : Symbol(a, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 3, 3)) + +let b = a || "foo"; +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) +>a : Symbol(a, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 3, 3)) + +let c: "foo" = b; +>c : Symbol(c, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 5, 3)) +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) + +let d = b || "bar"; +>d : Symbol(d, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 6, 3)) +>b : Symbol(b, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 4, 3)) + +let e: "foo" | "bar" = d; +>e : Symbol(e, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 7, 3)) +>d : Symbol(d, Decl(stringLiteralTypesAndLogicalOrExpressions01.ts, 6, 3)) + diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types new file mode 100644 index 00000000000..ddc79b81857 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : () => boolean + +let a: "foo" = "foo"; +>a : "foo" +>"foo" : "foo" + +let b = a || "foo"; +>b : "foo" +>a || "foo" : "foo" +>a : "foo" +>"foo" : "foo" + +let c: "foo" = b; +>c : "foo" +>b : "foo" + +let d = b || "bar"; +>d : "foo" | "bar" +>b || "bar" : "foo" | "bar" +>b : "foo" +>"bar" : "bar" + +let e: "foo" | "bar" = d; +>e : "foo" | "bar" +>d : "foo" | "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt new file mode 100644 index 00000000000..93d8a213d0f --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt @@ -0,0 +1,17 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(4,5): error TS2322: Type 'string' is not assignable to type '"foo"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(6,5): error TS2322: Type 'string' is not assignable to type '"foo"'. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts (2 errors) ==== + + declare function myRandBool(): boolean; + + let a: "foo" = ("foo"); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"foo"'. + let b: "foo" | "bar" = ("foo"); + let c: "foo" = (myRandBool ? "foo" : ("foo")); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"foo"'. + let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); + \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js new file mode 100644 index 00000000000..1fe1225c6f4 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.js @@ -0,0 +1,23 @@ +//// [stringLiteralTypesAndParenthesizedExpressions01.ts] + +declare function myRandBool(): boolean; + +let a: "foo" = ("foo"); +let b: "foo" | "bar" = ("foo"); +let c: "foo" = (myRandBool ? "foo" : ("foo")); +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); + + +//// [stringLiteralTypesAndParenthesizedExpressions01.js] +var a = ("foo"); +var b = ("foo"); +var c = (myRandBool ? "foo" : ("foo")); +var d = (myRandBool ? "foo" : ("bar")); + + +//// [stringLiteralTypesAndParenthesizedExpressions01.d.ts] +declare function myRandBool(): boolean; +declare let a: "foo"; +declare let b: "foo" | "bar"; +declare let c: "foo"; +declare let d: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.js b/tests/baselines/reference/stringLiteralTypesOverloads04.js new file mode 100644 index 00000000000..fd10ac986a9 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.js @@ -0,0 +1,18 @@ +//// [stringLiteralTypesOverloads04.ts] + +declare function f(x: (p: "foo" | "bar") => "foo"); + +f(y => { + let z = y = "foo"; + return z; +}) + +//// [stringLiteralTypesOverloads04.js] +f(function (y) { + var z = y = "foo"; + return z; +}); + + +//// [stringLiteralTypesOverloads04.d.ts] +declare function f(x: (p: "foo" | "bar") => "foo"): any; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.symbols b/tests/baselines/reference/stringLiteralTypesOverloads04.symbols new file mode 100644 index 00000000000..9f468b8bd95 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts === + +declare function f(x: (p: "foo" | "bar") => "foo"); +>f : Symbol(f, Decl(stringLiteralTypesOverloads04.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads04.ts, 1, 19)) +>p : Symbol(p, Decl(stringLiteralTypesOverloads04.ts, 1, 23)) + +f(y => { +>f : Symbol(f, Decl(stringLiteralTypesOverloads04.ts, 0, 0)) +>y : Symbol(y, Decl(stringLiteralTypesOverloads04.ts, 3, 2)) + + let z = y = "foo"; +>z : Symbol(z, Decl(stringLiteralTypesOverloads04.ts, 4, 7)) +>y : Symbol(y, Decl(stringLiteralTypesOverloads04.ts, 3, 2)) + + return z; +>z : Symbol(z, Decl(stringLiteralTypesOverloads04.ts, 4, 7)) + +}) diff --git a/tests/baselines/reference/stringLiteralTypesOverloads04.types b/tests/baselines/reference/stringLiteralTypesOverloads04.types new file mode 100644 index 00000000000..32d316494ca --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads04.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads04.ts === + +declare function f(x: (p: "foo" | "bar") => "foo"); +>f : (x: (p: "foo" | "bar") => "foo") => any +>x : (p: "foo" | "bar") => "foo" +>p : "foo" | "bar" + +f(y => { +>f(y => { let z = y = "foo"; return z;}) : any +>f : (x: (p: "foo" | "bar") => "foo") => any +>y => { let z = y = "foo"; return z;} : (y: "foo" | "bar") => "foo" +>y : "foo" | "bar" + + let z = y = "foo"; +>z : "foo" +>y = "foo" : "foo" +>y : "foo" | "bar" +>"foo" : "foo" + + return z; +>z : "foo" + +}) From 97d170b388102bded0fdd68384c3a43b4f871fe6 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 13:10:44 -0800 Subject: [PATCH 25/93] Support to tests for absolute paths, add common src dir edgecase tests --- src/harness/compilerRunner.ts | 22 ++++++------------- tests/baselines/reference/commonSourceDir1.js | 13 +++++++++++ .../reference/commonSourceDir1.symbols | 8 +++++++ .../reference/commonSourceDir1.types | 8 +++++++ .../reference/commonSourceDir2.errors.txt | 9 ++++++++ tests/baselines/reference/commonSourceDir2.js | 12 ++++++++++ tests/baselines/reference/commonSourceDir3.js | 12 ++++++++++ .../reference/commonSourceDir3.symbols | 8 +++++++ .../reference/commonSourceDir3.types | 8 +++++++ .../reference/commonSourceDir4.errors.txt | 9 ++++++++ tests/baselines/reference/commonSourceDir4.js | 12 ++++++++++ tests/cases/compiler/commonSourceDir1.ts | 6 +++++ tests/cases/compiler/commonSourceDir2.ts | 6 +++++ tests/cases/compiler/commonSourceDir3.ts | 6 +++++ tests/cases/compiler/commonSourceDir4.ts | 7 ++++++ 15 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 tests/baselines/reference/commonSourceDir1.js create mode 100644 tests/baselines/reference/commonSourceDir1.symbols create mode 100644 tests/baselines/reference/commonSourceDir1.types create mode 100644 tests/baselines/reference/commonSourceDir2.errors.txt create mode 100644 tests/baselines/reference/commonSourceDir2.js create mode 100644 tests/baselines/reference/commonSourceDir3.js create mode 100644 tests/baselines/reference/commonSourceDir3.symbols create mode 100644 tests/baselines/reference/commonSourceDir3.types create mode 100644 tests/baselines/reference/commonSourceDir4.errors.txt create mode 100644 tests/baselines/reference/commonSourceDir4.js create mode 100644 tests/cases/compiler/commonSourceDir1.ts create mode 100644 tests/cases/compiler/commonSourceDir2.ts create mode 100644 tests/cases/compiler/commonSourceDir3.ts create mode 100644 tests/cases/compiler/commonSourceDir4.ts diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 848f229f109..f7bb23527dd 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -45,14 +45,10 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let justName: string; - let content: string; - let testCaseContent: { settings: Harness.TestCaseParser.CompilerSettings; testUnitData: Harness.TestCaseParser.TestUnitData[]; }; - let units: Harness.TestCaseParser.TestUnitData[]; let tcSettings: Harness.TestCaseParser.CompilerSettings; let lastUnit: Harness.TestCaseParser.TestUnitData; - let rootDir: string; let result: Harness.Compiler.CompilerResult; let program: ts.Program; @@ -65,12 +61,12 @@ class CompilerBaselineRunner extends RunnerBase { before(() => { justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path. - content = Harness.IO.readFile(fileName); - testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); - units = testCaseContent.testUnitData; + const content = Harness.IO.readFile(fileName); + const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); + const units = testCaseContent.testUnitData; tcSettings = testCaseContent.settings; lastUnit = units[units.length - 1]; - rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; + const 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, @@ -78,16 +74,16 @@ class CompilerBaselineRunner extends RunnerBase { 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.isRootedDiskPath(lastUnit.name) ? lastUnit.name : 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.isRootedDiskPath(unit.name) ? unit.name : rootDir + unit.name, content: unit.content }); } }); } else { toBeCompiled = units.map(unit => { - return { unitName: rootDir + unit.name, content: unit.content }; + return { unitName: ts.isRootedDiskPath(unit.name) ? unit.name : rootDir + unit.name, content: unit.content }; }); } @@ -104,12 +100,8 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. justName = undefined; - content = undefined; - testCaseContent = undefined; - units = undefined; tcSettings = undefined; lastUnit = undefined; - rootDir = undefined; result = undefined; program = undefined; options = undefined; diff --git a/tests/baselines/reference/commonSourceDir1.js b/tests/baselines/reference/commonSourceDir1.js new file mode 100644 index 00000000000..68833aed49d --- /dev/null +++ b/tests/baselines/reference/commonSourceDir1.js @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/commonSourceDir1.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/commonSourceDir1.symbols b/tests/baselines/reference/commonSourceDir1.symbols new file mode 100644 index 00000000000..9248e0c97af --- /dev/null +++ b/tests/baselines/reference/commonSourceDir1.symbols @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : Symbol(x, Decl(bar.ts, 0, 3)) + +=== A:/foo/baz.ts === +var y: number; +>y : Symbol(y, Decl(baz.ts, 0, 3)) + diff --git a/tests/baselines/reference/commonSourceDir1.types b/tests/baselines/reference/commonSourceDir1.types new file mode 100644 index 00000000000..6c9864c02cc --- /dev/null +++ b/tests/baselines/reference/commonSourceDir1.types @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : number + +=== A:/foo/baz.ts === +var y: number; +>y : number + diff --git a/tests/baselines/reference/commonSourceDir2.errors.txt b/tests/baselines/reference/commonSourceDir2.errors.txt new file mode 100644 index 00000000000..85bcf5d9c72 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir2.errors.txt @@ -0,0 +1,9 @@ +error TS5009: Cannot find the common subdirectory path for the input files. + + +!!! error TS5009: Cannot find the common subdirectory path for the input files. +==== A:/foo/bar.ts (0 errors) ==== + var x: number; + +==== B:/foo/baz.ts (0 errors) ==== + var y: number; \ No newline at end of file diff --git a/tests/baselines/reference/commonSourceDir2.js b/tests/baselines/reference/commonSourceDir2.js new file mode 100644 index 00000000000..cf263b51fb6 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir2.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir2.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/commonSourceDir3.js b/tests/baselines/reference/commonSourceDir3.js new file mode 100644 index 00000000000..0535d51f4bf --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir3.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/baselines/reference/commonSourceDir3.symbols b/tests/baselines/reference/commonSourceDir3.symbols new file mode 100644 index 00000000000..b8783523dfd --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.symbols @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : Symbol(x, Decl(bar.ts, 0, 3)) + +=== a:/foo/baz.ts === +var y: number; +>y : Symbol(y, Decl(baz.ts, 0, 3)) + diff --git a/tests/baselines/reference/commonSourceDir3.types b/tests/baselines/reference/commonSourceDir3.types new file mode 100644 index 00000000000..a0b95275897 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir3.types @@ -0,0 +1,8 @@ +=== A:/foo/bar.ts === +var x: number; +>x : number + +=== a:/foo/baz.ts === +var y: number; +>y : number + diff --git a/tests/baselines/reference/commonSourceDir4.errors.txt b/tests/baselines/reference/commonSourceDir4.errors.txt new file mode 100644 index 00000000000..f3493504e4d --- /dev/null +++ b/tests/baselines/reference/commonSourceDir4.errors.txt @@ -0,0 +1,9 @@ +error TS5009: Cannot find the common subdirectory path for the input files. + + +!!! error TS5009: Cannot find the common subdirectory path for the input files. +==== A:/foo/bar.ts (0 errors) ==== + var x: number; + +==== a:/foo/baz.ts (0 errors) ==== + var y: number; \ No newline at end of file diff --git a/tests/baselines/reference/commonSourceDir4.js b/tests/baselines/reference/commonSourceDir4.js new file mode 100644 index 00000000000..2f2af9f68b2 --- /dev/null +++ b/tests/baselines/reference/commonSourceDir4.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/commonSourceDir4.ts] //// + +//// [bar.ts] +var x: number; + +//// [baz.ts] +var y: number; + +//// [bar.js] +var x; +//// [baz.js] +var y; diff --git a/tests/cases/compiler/commonSourceDir1.ts b/tests/cases/compiler/commonSourceDir1.ts new file mode 100644 index 00000000000..1a178ac0226 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir1.ts @@ -0,0 +1,6 @@ +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: A:/foo/baz.ts +var y: number; diff --git a/tests/cases/compiler/commonSourceDir2.ts b/tests/cases/compiler/commonSourceDir2.ts new file mode 100644 index 00000000000..68dab0727a3 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir2.ts @@ -0,0 +1,6 @@ +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: B:/foo/baz.ts +var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/commonSourceDir3.ts b/tests/cases/compiler/commonSourceDir3.ts new file mode 100644 index 00000000000..cc42eb8f267 --- /dev/null +++ b/tests/cases/compiler/commonSourceDir3.ts @@ -0,0 +1,6 @@ +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: a:/foo/baz.ts +var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/commonSourceDir4.ts b/tests/cases/compiler/commonSourceDir4.ts new file mode 100644 index 00000000000..41ee7a0344a --- /dev/null +++ b/tests/cases/compiler/commonSourceDir4.ts @@ -0,0 +1,7 @@ +// @useCaseSensitiveFileNames: true +// @outDir: A:/ +// @Filename: A:/foo/bar.ts +var x: number; + +// @Filename: a:/foo/baz.ts +var y: number; \ No newline at end of file From 00130f1a68011ae59fb61e2f70897d48ec100b47 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 13:20:28 -0800 Subject: [PATCH 26/93] Handle when using -p and config file not found --- src/compiler/tsc.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 474d7212070..f560a15dfb9 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -346,6 +346,12 @@ namespace ts { return; } } + if (!cachedConfigFileText) { + const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName); + reportDiagnostics([error], /* compilerHost */ undefined); + sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText); const configObject = result.config; From a1cf51faacf18f4a3f91530688ec2c77fefd698d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 13:25:09 -0800 Subject: [PATCH 27/93] use canonical filename function --- src/compiler/program.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index aee66834a11..03305dd368d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -894,7 +894,7 @@ namespace ts { return; } - const sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory); + const sourcePathComponents = getNormalizedPathComponents(getCanonicalFileName(sourceFile.fileName), currentDirectory); sourcePathComponents.pop(); // The base file name is not part of the common directory path if (!commonPathComponents) { @@ -903,9 +903,8 @@ namespace ts { return; } - const caseSensitive = host.useCaseSensitiveFileNames(); for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (caseSensitive ? commonPathComponents[i] !== sourcePathComponents[i] : commonPathComponents[i].toLocaleLowerCase() !== sourcePathComponents[i].toLocaleLowerCase()) { + if (commonPathComponents[i] !== sourcePathComponents[i]) { if (i === 0) { // Failed to find any common path component return true; From 79b7146d0bbb3c80cb3a73a6fa2d86894af97d6a Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 10 Nov 2015 13:30:26 -0800 Subject: [PATCH 28/93] Cleanup of types --- src/compiler/checker.ts | 2 +- src/compiler/parser.ts | 56 +++---- src/compiler/types.ts | 337 +++++++++++++++++++++++++++++++++----- src/compiler/utilities.ts | 4 +- src/services/services.ts | 96 +++++------ 5 files changed, 371 insertions(+), 124 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f1593abb177..bfd2eb8d7b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9766,7 +9766,7 @@ namespace ts { return type; } - function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) { + function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const isAsync = isAsyncFunctionLike(node); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 18e9cdea406..39b5a5d322e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1082,7 +1082,7 @@ namespace ts { token === SyntaxKind.NumericLiteral; } - function parsePropertyNameWorker(allowComputedPropertyNames: boolean): DeclarationName { + function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) { return parseLiteralNode(/*internName*/ true); } @@ -1092,7 +1092,7 @@ namespace ts { return parseIdentifierName(); } - function parsePropertyName(): DeclarationName { + function parsePropertyName(): PropertyName { return parsePropertyNameWorker(/*allowComputedPropertyNames:*/ true); } @@ -1152,7 +1152,7 @@ namespace ts { } function parseAnyContextualModifier(): boolean { - return isModifier(token) && tryParse(nextTokenCanFollowModifier); + return isModifierKind(token) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier(): boolean { @@ -1999,7 +1999,7 @@ namespace ts { } function isStartOfParameter(): boolean { - return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifier(token) || token === SyntaxKind.AtToken; + return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken; } function setModifiers(node: Node, modifiers: ModifiersArray) { @@ -2020,7 +2020,7 @@ namespace ts { node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) { + if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifierKind(token)) { // in cases like // 'use strict' // function foo(static) @@ -2127,8 +2127,8 @@ namespace ts { parseSemicolon(); } - function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration { - const node = createNode(kind); + function parseSignatureMember(kind: SyntaxKind): CallSignatureDeclaration | ConstructSignatureDeclaration { + const node = createNode(kind); if (kind === SyntaxKind.ConstructSignature) { parseExpected(SyntaxKind.NewKeyword); } @@ -2167,7 +2167,7 @@ namespace ts { return true; } - if (isModifier(token)) { + if (isModifierKind(token)) { nextToken(); if (isIdentifier()) { return true; @@ -2210,13 +2210,13 @@ namespace ts { return finishNode(node); } - function parsePropertyOrMethodSignature(): Declaration { + function parsePropertyOrMethodSignature(): PropertySignature | MethodSignature { const fullStart = scanner.getStartPos(); const name = parsePropertyName(); const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { - const method = createNode(SyntaxKind.MethodSignature, fullStart); + const method = createNode(SyntaxKind.MethodSignature, fullStart); method.name = name; method.questionToken = questionToken; @@ -2227,7 +2227,7 @@ namespace ts { return finishNode(method); } else { - const property = createNode(SyntaxKind.PropertySignature, fullStart); + const property = createNode(SyntaxKind.PropertySignature, fullStart); property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -2243,7 +2243,7 @@ namespace ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - if (isModifier(token)) { + if (isModifierKind(token)) { const result = lookAhead(isStartOfIndexSignatureDeclaration); if (result) { return result; @@ -2255,7 +2255,7 @@ namespace ts { } function isStartOfIndexSignatureDeclaration() { - while (isModifier(token)) { + while (isModifierKind(token)) { nextToken(); } @@ -2271,7 +2271,7 @@ namespace ts { canParseSemicolon(); } - function parseTypeMember(): Declaration { + function parseTypeMember(): TypeElement { switch (token) { case SyntaxKind.OpenParenToken: case SyntaxKind.LessThanToken: @@ -2296,7 +2296,7 @@ namespace ts { // when incrementally parsing as the parser will produce the Index declaration // if it has the same text regardless of whether it is inside a class or an // object type. - if (isModifier(token)) { + if (isModifierKind(token)) { const result = tryParse(parseIndexSignatureWithModifiers); if (result) { return result; @@ -2329,14 +2329,14 @@ namespace ts { return finishNode(node); } - function parseObjectTypeMembers(): NodeArray { - let members: NodeArray; + function parseObjectTypeMembers(): NodeArray { + let members: NodeArray; if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, parseTypeMember); parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } return members; @@ -2478,11 +2478,11 @@ namespace ts { // ( ... return true; } - if (isIdentifier() || isModifier(token)) { + if (isIdentifier() || isModifierKind(token)) { nextToken(); if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || - isIdentifier() || isModifier(token)) { + isIdentifier() || isModifierKind(token)) { // ( id : // ( id , // ( id ? @@ -2889,7 +2889,7 @@ namespace ts { } // This *could* be a parenthesized arrow function. - // Return Unknown to const the caller know. + // Return Unknown to let the caller know. return Tristate.Unknown; } else { @@ -2988,7 +2988,7 @@ namespace ts { // user meant to supply a block. For example, if the user wrote: // // a => - // const v = 0; + // let v = 0; // } // // they may be missing an open brace. Check to see if that's the case so we can @@ -3215,7 +3215,7 @@ namespace ts { /** * Parse ES7 unary expression and await expression - * + * * ES7 UnaryExpression: * 1) SimpleUnaryExpression[?yield] * 2) IncrementExpression[?yield] ** UnaryExpression[?yield] @@ -4716,7 +4716,7 @@ namespace ts { return finishNode(node); } - function parseMethodDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, asteriskToken: Node, name: DeclarationName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration { + function parseMethodDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration { const method = createNode(SyntaxKind.MethodDeclaration, fullStart); method.decorators = decorators; setModifiers(method, modifiers); @@ -4730,7 +4730,7 @@ namespace ts { return finishNode(method); } - function parsePropertyDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, name: DeclarationName, questionToken: Node): ClassElement { + function parsePropertyDeclaration(fullStart: number, decorators: NodeArray, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement { const property = createNode(SyntaxKind.PropertyDeclaration, fullStart); property.decorators = decorators; setModifiers(property, modifiers); @@ -4804,7 +4804,7 @@ namespace ts { } // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. - while (isModifier(token)) { + while (isModifierKind(token)) { idToken = token; // If the idToken is a class modifier (protected, private, public, and static), it is // certain that we are starting to parse class member. This allows better error recovery @@ -5014,8 +5014,8 @@ namespace ts { // implements is a future reserved word so // 'class implements' might mean either // - class expression with omitted name, 'implements' starts heritage clause - // - class with name 'implements' - // 'isImplementsClause' helps to disambiguate between these two cases + // - class with name 'implements' + // 'isImplementsClause' helps to disambiguate between these two cases return isIdentifier() && !isImplementsClause() ? parseIdentifier() : undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 08313f832a2..2489c049b68 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -348,7 +348,7 @@ namespace ts { LastKeyword = OfKeyword, FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, - FirstTypeNode = TypeReference, + FirstTypeNode = TypePredicate, LastTypeNode = ParenthesizedType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, @@ -474,15 +474,29 @@ namespace ts { hasTrailingComma?: boolean; } - export interface ModifiersArray extends NodeArray { + export interface ModifiersArray extends NodeArray { flags: number; } + // @kind(SyntaxKind.AbstractKeyword) + // @kind(SyntaxKind.AsyncKeyword) + // @kind(SyntaxKind.ConstKeyword) + // @kind(SyntaxKind.DeclareKeyword) + // @kind(SyntaxKind.DefaultKeyword) + // @kind(SyntaxKind.ExportKeyword) + // @kind(SyntaxKind.PublicKeyword) + // @kind(SyntaxKind.PrivateKeyword) + // @kind(SyntaxKind.ProtectedKeyword) + // @kind(SyntaxKind.StaticKeyword) + export interface Modifier extends Node { } + + // @kind(SyntaxKind.Identifier) export interface Identifier extends PrimaryExpression { text: string; // Text of identifier (with escapes converted to characters) originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later } + // @kind(SyntaxKind.QualifiedName) export interface QualifiedName extends Node { // Must have same layout as PropertyAccess left: EntityName; @@ -491,6 +505,8 @@ namespace ts { export type EntityName = Identifier | QualifiedName; + export type PropertyName = Identifier | LiteralExpression | ComputedPropertyName; + export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; export interface Declaration extends Node { @@ -498,14 +514,21 @@ namespace ts { name?: DeclarationName; } + export interface DeclarationStatement extends Declaration, Statement { + name?: Identifier; + } + + // @kind(SyntaxKind.ComputedPropertyName) export interface ComputedPropertyName extends Node { expression: Expression; } + // @kind(SyntaxKind.Decorator) export interface Decorator extends Node { expression: LeftHandSideExpression; } + // @kind(SyntaxKind.TypeParameter) export interface TypeParameterDeclaration extends Declaration { name: Identifier; constraint?: TypeNode; @@ -515,12 +538,19 @@ namespace ts { } export interface SignatureDeclaration extends Declaration { + name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; type?: TypeNode; } - // SyntaxKind.VariableDeclaration + // @kind(SyntaxKind.CallSignature) + export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement { } + + // @kind(SyntaxKind.ConstructSignature) + export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { } + + // @kind(SyntaxKind.VariableDeclaration) export interface VariableDeclaration extends Declaration { parent?: VariableDeclarationList; name: Identifier | BindingPattern; // Declared variable name @@ -528,11 +558,12 @@ namespace ts { initializer?: Expression; // Optional initializer } + // @kind(SyntaxKind.VariableDeclarationList) export interface VariableDeclarationList extends Node { declarations: NodeArray; } - // SyntaxKind.Parameter + // @kind(SyntaxKind.Parameter) export interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; // Present on rest parameter name: Identifier | BindingPattern; // Declared parameter name @@ -541,7 +572,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - // SyntaxKind.BindingElement + // @kind(SyntaxKind.BindingElement) export interface BindingElement extends Declaration { propertyName?: Identifier; // Binding property name (in object binding pattern) dotDotDotToken?: Node; // Present on rest binding element @@ -549,27 +580,35 @@ namespace ts { initializer?: Expression; // Optional initializer } - // SyntaxKind.Property - export interface PropertyDeclaration extends Declaration, ClassElement { - name: DeclarationName; // Declared property name + // @kind(SyntaxKind.PropertySignature) + export interface PropertySignature extends TypeElement { + name: PropertyName; // Declared property name questionToken?: Node; // Present on optional property type?: TypeNode; // Optional type annotation + } + + // @kind(SyntaxKind.PropertyDeclaration) + export interface PropertyDeclaration extends ClassElement { + questionToken?: Node; // Present for use with reporting a grammar error + name: PropertyName; + type?: TypeNode; initializer?: Expression; // Optional initializer } export interface ObjectLiteralElement extends Declaration { _objectLiteralBrandBrand: any; - } + name?: PropertyName; + } - // SyntaxKind.PropertyAssignment + // @kind(SyntaxKind.PropertyAssignment) export interface PropertyAssignment extends ObjectLiteralElement { _propertyAssignmentBrand: any; - name: DeclarationName; + name: PropertyName; questionToken?: Node; initializer: Expression; } - // SyntaxKind.ShorthandPropertyAssignment + // @kind(SyntaxKind.ShorthandPropertyAssignment) export interface ShorthandPropertyAssignment extends ObjectLiteralElement { name: Identifier; questionToken?: Node; @@ -595,10 +634,20 @@ namespace ts { initializer?: Expression; } + export interface PropertyLikeDeclaration extends Declaration { + name: PropertyName; + } + export interface BindingPattern extends Node { elements: NodeArray; } + // @kind(SyntaxKind.ObjectBindingPattern) + export interface ObjectBindingPattern extends BindingPattern { } + + // @kind(SyntaxKind.ArrayBindingPattern) + export interface ArrayBindingPattern extends BindingPattern { } + /** * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. @@ -615,9 +664,15 @@ namespace ts { body?: Block | Expression; } - export interface FunctionDeclaration extends FunctionLikeDeclaration, Statement { + // @kind(SyntaxKind.FunctionDeclaration) + export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement { name?: Identifier; - body?: Block; + body?: FunctionBody; + } + + // @kind(SyntaxKind.MethodSignature) + export interface MethodSignature extends SignatureDeclaration, TypeElement { + name: PropertyName; } // Note that a MethodDeclaration is considered both a ClassElement and an ObjectLiteralElement. @@ -629,15 +684,19 @@ namespace ts { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration + // @kind(SyntaxKind.MethodDeclaration) export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { - body?: Block; + name: PropertyName; + body?: FunctionBody; } + // @kind(SyntaxKind.Constructor) export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { - body?: Block; + body?: FunctionBody; } // For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. + // @kind(SyntaxKind.SemicolonClassElement) export interface SemicolonClassElement extends ClassElement { _semicolonClassElementBrand: any; } @@ -646,13 +705,27 @@ namespace ts { // ClassElement and an ObjectLiteralElement. export interface AccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { _accessorDeclarationBrand: any; - body: Block; + name: PropertyName; + body: FunctionBody; } - export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement { + // @kind(SyntaxKind.GetAccessor) + export interface GetAccessorDeclaration extends AccessorDeclaration { } + + // @kind(SyntaxKind.SetAccessor) + export interface SetAccessorDeclaration extends AccessorDeclaration { } + + // @kind(SyntaxKind.IndexSignature) + export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement { _indexSignatureDeclarationBrand: any; } + // @kind(SyntaxKind.AnyKeyword) + // @kind(SyntaxKind.NumberKeyword) + // @kind(SyntaxKind.BooleanKeyword) + // @kind(SyntaxKind.StringKeyword) + // @kind(SyntaxKind.SymbolKeyword) + // @kind(SyntaxKind.VoidKeyword) export interface TypeNode extends Node { _typeNodeBrand: any; } @@ -661,29 +734,41 @@ namespace ts { _functionOrConstructorTypeNodeBrand: any; } + // @kind(SyntaxKind.FunctionType) + export interface FunctionTypeNode extends FunctionOrConstructorTypeNode { } + + // @kind(SyntaxKind.ConstructorType) + export interface ConstructorTypeNode extends FunctionOrConstructorTypeNode { } + + // @kind(SyntaxKind.TypeReference) export interface TypeReferenceNode extends TypeNode { typeName: EntityName; typeArguments?: NodeArray; } + // @kind(SyntaxKind.TypePredicate) export interface TypePredicateNode extends TypeNode { parameterName: Identifier; type: TypeNode; } + // @kind(SyntaxKind.TypeQuery) export interface TypeQueryNode extends TypeNode { exprName: EntityName; } // A TypeLiteral is the declaration node for an anonymous symbol. + // @kind(SyntaxKind.TypeLiteral) export interface TypeLiteralNode extends TypeNode, Declaration { - members: NodeArray; + members: NodeArray; } + // @kind(SyntaxKind.ArrayType) export interface ArrayTypeNode extends TypeNode { elementType: TypeNode; } + // @kind(SyntaxKind.TupleType) export interface TupleTypeNode extends TypeNode { elementTypes: NodeArray; } @@ -692,16 +777,20 @@ namespace ts { types: NodeArray; } + // @kind(SyntaxKind.UnionType) export interface UnionTypeNode extends UnionOrIntersectionTypeNode { } + // @kind(SyntaxKind.IntersectionType) export interface IntersectionTypeNode extends UnionOrIntersectionTypeNode { } + // @kind(SyntaxKind.ParenthesizedType) export interface ParenthesizedTypeNode extends TypeNode { type: TypeNode; } // Note that a StringLiteral AST node is both an Expression and a TypeNode. The latter is // because string literals can appear in type annotations as well. + // @kind(SyntaxKind.StringLiteral) export interface StringLiteral extends LiteralExpression, TypeNode { _stringLiteralBrand: any; } @@ -718,6 +807,9 @@ namespace ts { contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution } + // @kind(SyntaxKind.OmittedExpression) + export interface OmittedExpression extends Expression { } + export interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } @@ -726,11 +818,13 @@ namespace ts { _incrementExpressionBrand: any; } + // @kind(SyntaxKind.PrefixUnaryExpression) export interface PrefixUnaryExpression extends IncrementExpression { operator: SyntaxKind; operand: UnaryExpression; } + // @kind(SyntaxKind.PostfixUnaryExpression) export interface PostfixUnaryExpression extends IncrementExpression { operand: LeftHandSideExpression; operator: SyntaxKind; @@ -748,37 +842,49 @@ namespace ts { _memberExpressionBrand: any; } + // @kind(SyntaxKind.TrueKeyword) + // @kind(SyntaxKind.FalseKeyword) + // @kind(SyntaxKind.NullKeyword) + // @kind(SyntaxKind.ThisKeyword) + // @kind(SyntaxKind.SuperKeyword) export interface PrimaryExpression extends MemberExpression { _primaryExpressionBrand: any; } + // @kind(SyntaxKind.DeleteExpression) export interface DeleteExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.TypeOfExpression) export interface TypeOfExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.VoidExpression) export interface VoidExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.AwaitExpression) export interface AwaitExpression extends UnaryExpression { expression: UnaryExpression; } + // @kind(SyntaxKind.YieldExpression) export interface YieldExpression extends Expression { asteriskToken?: Node; expression?: Expression; } + // @kind(SyntaxKind.BinaryExpression) export interface BinaryExpression extends Expression { left: Expression; operatorToken: Node; right: Expression; } + // @kind(SyntaxKind.ConditionalExpression) export interface ConditionalExpression extends Expression { condition: Expression; questionToken: Node; @@ -787,24 +893,37 @@ namespace ts { whenFalse: Expression; } + export type FunctionBody = Block; + export type ConciseBody = FunctionBody | Expression; + + // @kind(SyntaxKind.FunctionExpression) export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration { name?: Identifier; - body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional + body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } + // @kind(SyntaxKind.ArrowFunction) export interface ArrowFunction extends Expression, FunctionLikeDeclaration { equalsGreaterThanToken: Node; + body: ConciseBody; } // The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral, // or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters. // For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1". + // @kind(SyntaxKind.NumericLiteral) + // @kind(SyntaxKind.RegularExpressionLiteral) + // @kind(SyntaxKind.NoSubstitutionTemplateLiteral) + // @kind(SyntaxKind.TemplateHead) + // @kind(SyntaxKind.TemplateMiddle) + // @kind(SyntaxKind.TemplateTail) export interface LiteralExpression extends PrimaryExpression { text: string; isUnterminated?: boolean; hasExtendedUnicodeEscape?: boolean; } + // @kind(SyntaxKind.TemplateExpression) export interface TemplateExpression extends PrimaryExpression { head: LiteralExpression; templateSpans: NodeArray; @@ -812,52 +931,63 @@ namespace ts { // Each of these corresponds to a substitution expression and a template literal, in that order. // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. + // @kind(SyntaxKind.TemplateSpan) export interface TemplateSpan extends Node { expression: Expression; literal: LiteralExpression; } + // @kind(SyntaxKind.ParenthesizedExpression) export interface ParenthesizedExpression extends PrimaryExpression { expression: Expression; } + // @kind(SyntaxKind.ArrayLiteralExpression) export interface ArrayLiteralExpression extends PrimaryExpression { elements: NodeArray; } + // @kind(SyntaxKind.SpreadElementExpression) export interface SpreadElementExpression extends Expression { expression: Expression; } // An ObjectLiteralExpression is the declaration node for an anonymous symbol. + // @kind(SyntaxKind.ObjectLiteralExpression) export interface ObjectLiteralExpression extends PrimaryExpression, Declaration { properties: NodeArray; } + // @kind(SyntaxKind.PropertyAccessExpression) export interface PropertyAccessExpression extends MemberExpression { expression: LeftHandSideExpression; dotToken: Node; name: Identifier; } + // @kind(SyntaxKind.ElementAccessExpression) export interface ElementAccessExpression extends MemberExpression { expression: LeftHandSideExpression; argumentExpression?: Expression; } + // @kind(SyntaxKind.CallExpression) export interface CallExpression extends LeftHandSideExpression { expression: LeftHandSideExpression; typeArguments?: NodeArray; arguments: NodeArray; } + // @kind(SyntaxKind.ExpressionWithTypeArguments) export interface ExpressionWithTypeArguments extends TypeNode { expression: LeftHandSideExpression; typeArguments?: NodeArray; } + // @kind(SyntaxKind.NewExpression) export interface NewExpression extends CallExpression, PrimaryExpression { } + // @kind(SyntaxKind.TaggedTemplateExpression) export interface TaggedTemplateExpression extends MemberExpression { tag: LeftHandSideExpression; template: LiteralExpression | TemplateExpression; @@ -865,11 +995,13 @@ namespace ts { export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator; + // @kind(SyntaxKind.AsExpression) export interface AsExpression extends Expression { expression: Expression; type: TypeNode; } + // @kind(SyntaxKind.TypeAssertionExpression) export interface TypeAssertion extends UnaryExpression { type: TypeNode; expression: UnaryExpression; @@ -878,6 +1010,7 @@ namespace ts { export type AssertionExpression = TypeAssertion | AsExpression; /// A JSX expression of the form ... + // @kind(SyntaxKind.JsxElement) export interface JsxElement extends PrimaryExpression { openingElement: JsxOpeningElement; children: NodeArray; @@ -885,6 +1018,7 @@ namespace ts { } /// The opening element of a ... JsxElement + // @kind(SyntaxKind.JsxOpeningElement) export interface JsxOpeningElement extends Expression { _openingElementBrand?: any; tagName: EntityName; @@ -892,6 +1026,7 @@ namespace ts { } /// A JSX expression of the form + // @kind(SyntaxKind.JsxSelfClosingElement) export interface JsxSelfClosingElement extends PrimaryExpression, JsxOpeningElement { _selfClosingElementBrand?: any; } @@ -899,24 +1034,29 @@ namespace ts { /// Either the opening tag in a ... pair, or the lone in a self-closing form export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; + // @kind(SyntaxKind.JsxAttribute) export interface JsxAttribute extends Node { name: Identifier; /// JSX attribute initializers are optional; is sugar for initializer?: Expression; } + // @kind(SyntaxKind.JsxSpreadAttribute) export interface JsxSpreadAttribute extends Node { expression: Expression; } + // @kind(SyntaxKind.JsxClosingElement) export interface JsxClosingElement extends Node { tagName: EntityName; } + // @kind(SyntaxKind.JsxExpression) export interface JsxExpression extends Expression { expression?: Expression; } + // @kind(SyntaxKind.JsxText) export interface JsxText extends Node { _jsxTextExpressionBrand: any; } @@ -927,18 +1067,36 @@ namespace ts { _statementBrand: any; } + // @kind(SyntaxKind.EmptyStatement) + export interface EmptyStatement extends Statement { } + + // @kind(SyntaxKind.DebuggerStatement) + export interface DebuggerStatement extends Statement { } + + // @kind(SyntaxKind.MissingDeclaration) + // @factoryhidden("name", true) + export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + name?: Identifier; + } + + export type BlockLike = SourceFile | Block | ModuleBlock | CaseClause; + + // @kind(SyntaxKind.Block) export interface Block extends Statement { statements: NodeArray; } + // @kind(SyntaxKind.VariableStatement) export interface VariableStatement extends Statement { declarationList: VariableDeclarationList; } + // @kind(SyntaxKind.ExpressionStatement) export interface ExpressionStatement extends Statement { expression: Expression; } + // @kind(SyntaxKind.IfStatement) export interface IfStatement extends Statement { expression: Expression; thenStatement: Statement; @@ -949,78 +1107,101 @@ namespace ts { statement: Statement; } + // @kind(SyntaxKind.DoStatement) export interface DoStatement extends IterationStatement { expression: Expression; } + // @kind(SyntaxKind.WhileStatement) export interface WhileStatement extends IterationStatement { expression: Expression; } + // @kind(SyntaxKind.ForStatement) export interface ForStatement extends IterationStatement { initializer?: VariableDeclarationList | Expression; condition?: Expression; incrementor?: Expression; } + // @kind(SyntaxKind.ForInStatement) export interface ForInStatement extends IterationStatement { initializer: VariableDeclarationList | Expression; expression: Expression; } + // @kind(SyntaxKind.ForOfStatement) export interface ForOfStatement extends IterationStatement { initializer: VariableDeclarationList | Expression; expression: Expression; } - export interface BreakOrContinueStatement extends Statement { + // @kind(SyntaxKind.BreakStatement) + export interface BreakStatement extends Statement { label?: Identifier; } + // @kind(SyntaxKind.ContinueStatement) + export interface ContinueStatement extends Statement { + label?: Identifier; + } + + export type BreakOrContinueStatement = BreakStatement | ContinueStatement; + + // @kind(SyntaxKind.ReturnStatement) export interface ReturnStatement extends Statement { expression?: Expression; } + // @kind(SyntaxKind.WithStatement) export interface WithStatement extends Statement { expression: Expression; statement: Statement; } + // @kind(SyntaxKind.SwitchStatement) export interface SwitchStatement extends Statement { expression: Expression; caseBlock: CaseBlock; } + // @kind(SyntaxKind.CaseBlock) export interface CaseBlock extends Node { clauses: NodeArray; } + // @kind(SyntaxKind.CaseClause) export interface CaseClause extends Node { expression?: Expression; statements: NodeArray; } + // @kind(SyntaxKind.DefaultClause) export interface DefaultClause extends Node { statements: NodeArray; } export type CaseOrDefaultClause = CaseClause | DefaultClause; + // @kind(SyntaxKind.LabeledStatement) export interface LabeledStatement extends Statement { label: Identifier; statement: Statement; } + // @kind(SyntaxKind.ThrowStatement) export interface ThrowStatement extends Statement { expression: Expression; } + // @kind(SyntaxKind.TryStatement) export interface TryStatement extends Statement { tryBlock: Block; catchClause?: CatchClause; finallyBlock?: Block; } + // @kind(SyntaxKind.CatchClause) export interface CatchClause extends Node { variableDeclaration: VariableDeclaration; block: Block; @@ -1033,34 +1214,49 @@ namespace ts { members: NodeArray; } - export interface ClassDeclaration extends ClassLikeDeclaration, Statement { + // @kind(SyntaxKind.ClassDeclaration) + export interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement { + name?: Identifier; } + // @kind(SyntaxKind.ClassExpression) export interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression { } export interface ClassElement extends Declaration { _classElementBrand: any; + name?: PropertyName; } - export interface InterfaceDeclaration extends Declaration, Statement { + export interface TypeElement extends Declaration { + _typeElementBrand: any; + name?: PropertyName; + // @factoryparam + questionToken?: Node; + } + + // @kind(SyntaxKind.InterfaceDeclaration) + export interface InterfaceDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; - members: NodeArray; + members: NodeArray; } + // @kind(SyntaxKind.HeritageClause) export interface HeritageClause extends Node { token: SyntaxKind; types?: NodeArray; } - export interface TypeAliasDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.TypeAliasDeclaration) + export interface TypeAliasDeclaration extends DeclarationStatement { name: Identifier; typeParameters?: NodeArray; type: TypeNode; } + // @kind(SyntaxKind.EnumMember) export interface EnumMember extends Declaration { // This does include ComputedPropertyName, but the parser will give an error // if it parses a ComputedPropertyName in an EnumMember @@ -1068,21 +1264,27 @@ namespace ts { initializer?: Expression; } - export interface EnumDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.EnumDeclaration) + export interface EnumDeclaration extends DeclarationStatement { name: Identifier; members: NodeArray; } - export interface ModuleDeclaration extends Declaration, Statement { + export type ModuleBody = ModuleBlock | ModuleDeclaration; + + // @kind(SyntaxKind.ModuleDeclaration) + export interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } + // @kind(SyntaxKind.ModuleBlock) export interface ModuleBlock extends Node, Statement { statements: NodeArray; } - export interface ImportEqualsDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.ImportEqualsDeclaration) + export interface ImportEqualsDeclaration extends DeclarationStatement { name: Identifier; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external @@ -1090,6 +1292,7 @@ namespace ts { moduleReference: EntityName | ExternalModuleReference; } + // @kind(SyntaxKind.ExternalModuleReference) export interface ExternalModuleReference extends Node { expression?: Expression; } @@ -1098,6 +1301,7 @@ namespace ts { // import "mod" => importClause = undefined, moduleSpecifier = "mod" // In rest of the cases, module specifier is string literal corresponding to module // ImportClause information is shown at its declaration below. + // @kind(SyntaxKind.ImportDeclaration) export interface ImportDeclaration extends Statement { importClause?: ImportClause; moduleSpecifier: Expression; @@ -1109,36 +1313,51 @@ namespace ts { // import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns } // import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} + // @kind(SyntaxKind.ImportClause) export interface ImportClause extends Declaration { name?: Identifier; // Default binding namedBindings?: NamespaceImport | NamedImports; } + // @kind(SyntaxKind.NamespaceImport) export interface NamespaceImport extends Declaration { name: Identifier; } - export interface ExportDeclaration extends Declaration, Statement { + // @kind(SyntaxKind.ExportDeclaration) + export interface ExportDeclaration extends DeclarationStatement { exportClause?: NamedExports; moduleSpecifier?: Expression; } - export interface NamedImportsOrExports extends Node { - elements: NodeArray; + // @kind(SyntaxKind.NamedImports) + export interface NamedImports extends Node { + elements: NodeArray; } - export type NamedImports = NamedImportsOrExports; - export type NamedExports = NamedImportsOrExports; + // @kind(SyntaxKind.NamedExports) + export interface NamedExports extends Node { + elements: NodeArray; + } - export interface ImportOrExportSpecifier extends Declaration { + export type NamedImportsOrExports = NamedImports | NamedExports; + + // @kind(SyntaxKind.ImportSpecifier) + export interface ImportSpecifier extends Declaration { propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) name: Identifier; // Declared name } - export type ImportSpecifier = ImportOrExportSpecifier; - export type ExportSpecifier = ImportOrExportSpecifier; + // @kind(SyntaxKind.ExportSpecifier) + export interface ExportSpecifier extends Declaration { + propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) + name: Identifier; // Declared name + } - export interface ExportAssignment extends Declaration, Statement { + export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; + + // @kind(SyntaxKind.ExportAssignment) + export interface ExportAssignment extends DeclarationStatement { isExportEquals?: boolean; expression: Expression; } @@ -1153,6 +1372,7 @@ namespace ts { } // represents a top level: { type } expression in a JSDoc comment. + // @kind(SyntaxKind.JSDocTypeExpression) export interface JSDocTypeExpression extends Node { type: JSDocType; } @@ -1161,90 +1381,111 @@ namespace ts { _jsDocTypeBrand: any; } + // @kind(SyntaxKind.JSDocAllType) export interface JSDocAllType extends JSDocType { _JSDocAllTypeBrand: any; } + // @kind(SyntaxKind.JSDocUnknownType) export interface JSDocUnknownType extends JSDocType { _JSDocUnknownTypeBrand: any; } + // @kind(SyntaxKind.JSDocArrayType) export interface JSDocArrayType extends JSDocType { elementType: JSDocType; } + // @kind(SyntaxKind.JSDocUnionType) export interface JSDocUnionType extends JSDocType { types: NodeArray; } + // @kind(SyntaxKind.JSDocTupleType) export interface JSDocTupleType extends JSDocType { types: NodeArray; } + // @kind(SyntaxKind.JSDocNonNullableType) export interface JSDocNonNullableType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocNullableType) export interface JSDocNullableType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocRecordType) export interface JSDocRecordType extends JSDocType, TypeLiteralNode { members: NodeArray; } + // @kind(SyntaxKind.JSDocTypeReference) export interface JSDocTypeReference extends JSDocType { name: EntityName; typeArguments: NodeArray; } + // @kind(SyntaxKind.JSDocOptionalType) export interface JSDocOptionalType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocFunctionType) export interface JSDocFunctionType extends JSDocType, SignatureDeclaration { parameters: NodeArray; type: JSDocType; } + // @kind(SyntaxKind.JSDocVariadicType) export interface JSDocVariadicType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocConstructorType) export interface JSDocConstructorType extends JSDocType { type: JSDocType; } + // @kind(SyntaxKind.JSDocThisType) export interface JSDocThisType extends JSDocType { type: JSDocType; } - export interface JSDocRecordMember extends PropertyDeclaration { + // @kind(SyntaxKind.JSDocRecordMember) + export interface JSDocRecordMember extends PropertySignature { name: Identifier | LiteralExpression; type?: JSDocType; } + // @kind(SyntaxKind.JSDocComment) export interface JSDocComment extends Node { tags: NodeArray; } + // @kind(SyntaxKind.JSDocTag) export interface JSDocTag extends Node { atToken: Node; tagName: Identifier; } + // @kind(SyntaxKind.JSDocTemplateTag) export interface JSDocTemplateTag extends JSDocTag { typeParameters: NodeArray; } + // @kind(SyntaxKind.JSDocReturnTag) export interface JSDocReturnTag extends JSDocTag { typeExpression: JSDocTypeExpression; } + // @kind(SyntaxKind.JSDocTypeTag) export interface JSDocTypeTag extends JSDocTag { typeExpression: JSDocTypeExpression; } + // @kind(SyntaxKind.JSDocParameterTag) export interface JSDocParameterTag extends JSDocTag { preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; @@ -1252,7 +1493,13 @@ namespace ts { isBracketed: boolean; } + export interface AmdDependency { + path: string; + name: string; + } + // Source files are declarations when they are external modules. + // @kind(SyntaxKind.SourceFile) export interface SourceFile extends Declaration { statements: NodeArray; endOfFileToken: Node; @@ -1261,7 +1508,7 @@ namespace ts { /* internal */ path: Path; text: string; - amdDependencies: {path: string; name: string}[]; + amdDependencies: AmdDependency[]; moduleName: string; referencedFiles: FileReference[]; languageVariant: LanguageVariant; @@ -2336,7 +2583,7 @@ namespace ts { export interface ModuleResolutionHost { fileExists(fileName: string): boolean; // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' - // to determine location of bundled typings for node module + // to determine location of bundled typings for node module readFile(fileName: string): string; } @@ -2344,7 +2591,7 @@ namespace ts { resolvedFileName: string; /* * Denotes if 'resolvedFileName' is isExternalLibraryImport and thus should be proper external module: - * - be a .d.ts file + * - be a .d.ts file * - use top level imports\exports * - don't use tripleslash references */ @@ -2367,11 +2614,11 @@ namespace ts { getNewLine(): string; /* - * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of - * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler + * CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of + * module name resolution) or provide implementation for methods from ModuleResolutionHost (in this case compiler * will appply built-in module resolution logic and use members of ModuleResolutionHost to ask host specific questions). - * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just - * 'throw new Error("NotImplemented")' + * If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just + * 'throw new Error("NotImplemented")' */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 17d780df574..199ca4e636f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1273,7 +1273,7 @@ namespace ts { } // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationName(name: Node): boolean { + export function isDeclarationName(name: Node): name is Identifier | StringLiteral | LiteralExpression { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -1483,7 +1483,7 @@ namespace ts { return node.kind === SyntaxKind.Identifier && (node).text === "Symbol"; } - export function isModifier(token: SyntaxKind): boolean { + export function isModifierKind(token: SyntaxKind): boolean { switch (token) { case SyntaxKind.AbstractKeyword: case SyntaxKind.AsyncKeyword: diff --git a/src/services/services.ts b/src/services/services.ts index 113a52459e9..529a70b1453 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -132,43 +132,43 @@ namespace ts { let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); let emptyArray: any[] = []; - + const jsDocTagNames = [ - "augments", - "author", - "argument", - "borrows", - "class", - "constant", - "constructor", - "constructs", - "default", - "deprecated", - "description", - "event", - "example", - "extends", - "field", - "fileOverview", - "function", - "ignore", - "inner", - "lends", - "link", - "memberOf", - "name", - "namespace", - "param", - "private", - "property", - "public", - "requires", - "returns", - "see", - "since", - "static", - "throws", - "type", + "augments", + "author", + "argument", + "borrows", + "class", + "constant", + "constructor", + "constructs", + "default", + "deprecated", + "description", + "event", + "example", + "extends", + "field", + "fileOverview", + "function", + "ignore", + "inner", + "lends", + "link", + "memberOf", + "name", + "namespace", + "param", + "private", + "property", + "public", + "requires", + "returns", + "see", + "since", + "static", + "throws", + "type", "version" ]; let jsDocCompletionEntries: CompletionEntry[]; @@ -816,7 +816,7 @@ namespace ts { constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end) } - + public update(newText: string, textChangeRange: TextChangeRange): SourceFile { return updateSourceFile(this, newText, textChangeRange); } @@ -1030,7 +1030,7 @@ namespace ts { /* * LS host can optionally implement this method if it wants to be completely in charge of module name resolution. - * if implementation is omitted then language service will use built-in module resolution logic and get answers to + * if implementation is omitted then language service will use built-in module resolution logic and get answers to * host specific questions using 'getScriptSnapshot'. */ resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; @@ -1854,7 +1854,7 @@ namespace ts { * - allowNonTsExtensions = true * - noLib = true * - noResolve = true - */ + */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); @@ -2574,7 +2574,7 @@ namespace ts { } } - export function createLanguageService(host: LanguageServiceHost, + export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); @@ -2662,10 +2662,10 @@ namespace ts { getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => currentDirectory, - fileExists: (fileName): boolean => { + fileExists: (fileName): boolean => { // stub missing host functionality Debug.assert(!host.resolveModuleNames); - return hostCache.getOrCreateEntry(fileName) !== undefined; + return hostCache.getOrCreateEntry(fileName) !== undefined; }, readFile: (fileName): string => { // stub missing host functionality @@ -3068,7 +3068,7 @@ namespace ts { log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { - // The current position is next to the '@' sign, when no tag name being provided yet. + // The current position is next to the '@' sign, when no tag name being provided yet. // Provide a full list of tag names if (hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { isJsDocTagName = true; @@ -3101,7 +3101,7 @@ namespace ts { } if (!insideJsDocTagExpression) { - // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal // comment or the plain text part of a jsDoc comment, so no completion should be available log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); return undefined; @@ -3622,8 +3622,8 @@ namespace ts { case SyntaxKind.CloseBraceToken: if (parent && - parent.kind === SyntaxKind.JsxExpression && - parent.parent && + parent.kind === SyntaxKind.JsxExpression && + parent.parent && (parent.parent.kind === SyntaxKind.JsxAttribute)) { return parent.parent.parent; } @@ -3672,7 +3672,7 @@ namespace ts { containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A Date: Tue, 10 Nov 2015 13:36:19 -0800 Subject: [PATCH 29/93] 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 2a370c9aa7ad5d1d12fb83508f99cd1f08b42d2b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 14:40:19 -0800 Subject: [PATCH 30/93] Added tests for string literal types used as generic constraints. --- ...LiteralTypesAsTypeParameterConstraint01.ts | 19 +++++++++++++++++++ ...LiteralTypesAsTypeParameterConstraint02.ts | 8 ++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts new file mode 100644 index 00000000000..53f516f4209 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts @@ -0,0 +1,19 @@ +// @declaration: true + +function foo(f: (x: T) => T) { + return f; +} + +function bar(f: (x: T) => T) { + return f; +} + +let f = foo(x => x); +let fResult = f("foo"); + +let g = foo((x => x)); +let gResult = g("foo"); + +let h = bar(x => x); +let hResult = h("foo"); +hResult = h("bar"); \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts new file mode 100644 index 00000000000..fb3a019402d --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts @@ -0,0 +1,8 @@ +// @declaration: true + +function foo(f: (x: T) => T) { + return f; +} + +let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); +let fResult = f("foo"); \ No newline at end of file From ebd7d2d93e914819f1b15b4e7e75d7da3905adad Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Nov 2015 16:48:08 -0800 Subject: [PATCH 31/93] extract method --- src/harness/compilerRunner.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index f7bb23527dd..4a599e96812 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -40,6 +40,10 @@ class CompilerBaselineRunner extends RunnerBase { this.basePath += "/" + this.testSuiteName; } + private makeUnitName(name: string, root: string) { + return ts.isRootedDiskPath(name) ? name : (root + name); + }; + public checkTestCodeOutput(fileName: string) { describe("compiler tests for " + fileName, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. @@ -74,16 +78,16 @@ class CompilerBaselineRunner extends RunnerBase { toBeCompiled = []; otherFiles = []; if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) { - toBeCompiled.push({ unitName: ts.isRootedDiskPath(lastUnit.name) ? lastUnit.name : rootDir + lastUnit.name, content: lastUnit.content }); + toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content }); units.forEach(unit => { if (unit.name !== lastUnit.name) { - otherFiles.push({ unitName: ts.isRootedDiskPath(unit.name) ? unit.name : rootDir + unit.name, content: unit.content }); + otherFiles.push({ unitName: this.makeUnitName(unit.name, rootDir), content: unit.content }); } }); } else { toBeCompiled = units.map(unit => { - return { unitName: ts.isRootedDiskPath(unit.name) ? unit.name : rootDir + unit.name, content: unit.content }; + return { unitName: this.makeUnitName(unit.name, rootDir), content: unit.content }; }); } From 9d3d49d636e69715c45bcd5d3632531a61874927 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 16:17:28 -0800 Subject: [PATCH 32/93] Only get the apparent type when necessary. --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e0e9a6e620f..4fe04cae13a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6966,7 +6966,7 @@ namespace ts { else if (operator === SyntaxKind.BarBarToken) { // When an || expression has a contextual type, the operands are contextually typed by that type. When an || // expression has no contextual type, the right operand is contextually typed by the type of the left operand. - let type = getApparentTypeOfContextualType(binaryExpression); + let type = getContextualType(binaryExpression); if (!type && node === binaryExpression.right) { type = checkExpression(binaryExpression.left); } @@ -7081,7 +7081,7 @@ namespace ts { // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. function getContextualTypeForConditionalOperand(node: Expression): Type { const conditional = node.parent; - return node === conditional.whenTrue || node === conditional.whenFalse ? getApparentTypeOfContextualType(conditional) : undefined; + return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } function getContextualTypeForJsxExpression(expr: JsxExpression | JsxSpreadAttribute): Type { @@ -7160,7 +7160,7 @@ namespace ts { Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression); return getContextualTypeForSubstitutionExpression(parent.parent, node); case SyntaxKind.ParenthesizedExpression: - return getApparentTypeOfContextualType(parent); + return getContextualType(parent); case SyntaxKind.JsxExpression: case SyntaxKind.JsxSpreadAttribute: return getContextualTypeForJsxExpression(parent); From ce455dac2b3ce3b0255be7441b2f84a24f9369b1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 22:43:07 -0800 Subject: [PATCH 33/93] Accepted baselines. --- ...esAndParenthesizedExpressions01.errors.txt | 17 ----- ...TypesAndParenthesizedExpressions01.symbols | 19 +++++ ...alTypesAndParenthesizedExpressions01.types | 33 ++++++++ ...LiteralTypesAsTypeParameterConstraint01.js | 68 +++++++++++++++++ ...alTypesAsTypeParameterConstraint01.symbols | 60 +++++++++++++++ ...eralTypesAsTypeParameterConstraint01.types | 76 +++++++++++++++++++ ...ypesAsTypeParameterConstraint02.errors.txt | 15 ++++ ...LiteralTypesAsTypeParameterConstraint02.js | 21 +++++ 8 files changed, 292 insertions(+), 17 deletions(-) delete mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt deleted file mode 100644 index 93d8a213d0f..00000000000 --- a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.errors.txt +++ /dev/null @@ -1,17 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(4,5): error TS2322: Type 'string' is not assignable to type '"foo"'. -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts(6,5): error TS2322: Type 'string' is not assignable to type '"foo"'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts (2 errors) ==== - - declare function myRandBool(): boolean; - - let a: "foo" = ("foo"); - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo"'. - let b: "foo" | "bar" = ("foo"); - let c: "foo" = (myRandBool ? "foo" : ("foo")); - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo"'. - let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); - \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols new file mode 100644 index 00000000000..2206a5185c1 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + +let a: "foo" = ("foo"); +>a : Symbol(a, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 3, 3)) + +let b: "foo" | "bar" = ("foo"); +>b : Symbol(b, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 4, 3)) + +let c: "foo" = (myRandBool ? "foo" : ("foo")); +>c : Symbol(c, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 5, 3)) +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); +>d : Symbol(d, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 6, 3)) +>myRandBool : Symbol(myRandBool, Decl(stringLiteralTypesAndParenthesizedExpressions01.ts, 0, 0)) + diff --git a/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types new file mode 100644 index 00000000000..0bb2e1dd3c7 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAndParenthesizedExpressions01.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndParenthesizedExpressions01.ts === + +declare function myRandBool(): boolean; +>myRandBool : () => boolean + +let a: "foo" = ("foo"); +>a : "foo" +>("foo") : "foo" +>"foo" : "foo" + +let b: "foo" | "bar" = ("foo"); +>b : "foo" | "bar" +>("foo") : "foo" +>"foo" : "foo" + +let c: "foo" = (myRandBool ? "foo" : ("foo")); +>c : "foo" +>(myRandBool ? "foo" : ("foo")) : "foo" +>myRandBool ? "foo" : ("foo") : "foo" +>myRandBool : () => boolean +>"foo" : "foo" +>("foo") : "foo" +>"foo" : "foo" + +let d: "foo" | "bar" = (myRandBool ? "foo" : ("bar")); +>d : "foo" | "bar" +>(myRandBool ? "foo" : ("bar")) : "foo" | "bar" +>myRandBool ? "foo" : ("bar") : "foo" | "bar" +>myRandBool : () => boolean +>"foo" : "foo" +>("bar") : "bar" +>"bar" : "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js new file mode 100644 index 00000000000..558f6bdf4c2 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js @@ -0,0 +1,68 @@ +//// [stringLiteralTypesAsTypeParameterConstraint01.ts] + +function foo(f: (x: T) => T) { + return f; +} + +function bar(f: (x: T) => T) { + return f; +} + +let f = foo(x => x); +let fResult = f("foo"); + +let g = foo((x => x)); +let gResult = g("foo"); + +let h = bar(x => x); +let hResult = h("foo"); +hResult = h("bar"); + +//// [stringLiteralTypesAsTypeParameterConstraint01.js] +function foo(f) { + return f; +} +function bar(f) { + return f; +} +var f = foo(function (x) { return x; }); +var fResult = f("foo"); +var g = foo((function (x) { return x; })); +var gResult = g("foo"); +var h = bar(function (x) { return x; }); +var hResult = h("foo"); +hResult = h("bar"); + + +//// [stringLiteralTypesAsTypeParameterConstraint01.d.ts] +declare function foo(f: (x: T) => T): (x: T) => T; +declare function bar(f: (x: T) => T): (x: T) => T; +declare let f: (x: "foo") => "foo"; +declare let fResult: "foo"; +declare let g: (x: "foo") => "foo"; +declare let gResult: "foo"; +declare let h: (x: "foo" | "bar") => "foo" | "bar"; +declare let hResult: "foo" | "bar"; + + +//// [DtsFileErrors] + + +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts(3,16): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts(5,16): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.d.ts (2 errors) ==== + declare function foo(f: (x: T) => T): (x: T) => T; + declare function bar(f: (x: T) => T): (x: T) => T; + declare let f: (x: "foo") => "foo"; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + declare let fResult: "foo"; + declare let g: (x: "foo") => "foo"; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + declare let gResult: "foo"; + declare let h: (x: "foo" | "bar") => "foo" | "bar"; + declare let hResult: "foo" | "bar"; + \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols new file mode 100644 index 00000000000..fd633b6e4d9 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.symbols @@ -0,0 +1,60 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts === + +function foo(f: (x: T) => T) { +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 30)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 34)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 13)) + + return f; +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 1, 30)) +} + +function bar(f: (x: T) => T) { +>bar : Symbol(bar, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 3, 1)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 38)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 42)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) +>T : Symbol(T, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 13)) + + return f; +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 5, 38)) +} + +let f = foo(x => x); +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 3)) +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 12)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 12)) + +let fResult = f("foo"); +>fResult : Symbol(fResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 10, 3)) +>f : Symbol(f, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 9, 3)) + +let g = foo((x => x)); +>g : Symbol(g, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 3)) +>foo : Symbol(foo, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 0, 0)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 13)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 13)) + +let gResult = g("foo"); +>gResult : Symbol(gResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 13, 3)) +>g : Symbol(g, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 12, 3)) + +let h = bar(x => x); +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) +>bar : Symbol(bar, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 3, 1)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 12)) +>x : Symbol(x, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 12)) + +let hResult = h("foo"); +>hResult : Symbol(hResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 16, 3)) +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) + +hResult = h("bar"); +>hResult : Symbol(hResult, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 16, 3)) +>h : Symbol(h, Decl(stringLiteralTypesAsTypeParameterConstraint01.ts, 15, 3)) + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types new file mode 100644 index 00000000000..fe9163fc819 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types @@ -0,0 +1,76 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint01.ts === + +function foo(f: (x: T) => T) { +>foo : (f: (x: T) => T) => (x: T) => T +>T : T +>f : (x: T) => T +>x : T +>T : T +>T : T + + return f; +>f : (x: T) => T +} + +function bar(f: (x: T) => T) { +>bar : (f: (x: T) => T) => (x: T) => T +>T : T +>f : (x: T) => T +>x : T +>T : T +>T : T + + return f; +>f : (x: T) => T +} + +let f = foo(x => x); +>f : (x: "foo") => "foo" +>foo(x => x) : (x: "foo") => "foo" +>foo : (f: (x: T) => T) => (x: T) => T +>x => x : (x: "foo") => "foo" +>x : "foo" +>x : "foo" + +let fResult = f("foo"); +>fResult : "foo" +>f("foo") : "foo" +>f : (x: "foo") => "foo" +>"foo" : "foo" + +let g = foo((x => x)); +>g : (x: "foo") => "foo" +>foo((x => x)) : (x: "foo") => "foo" +>foo : (f: (x: T) => T) => (x: T) => T +>(x => x) : (x: "foo") => "foo" +>x => x : (x: "foo") => "foo" +>x : "foo" +>x : "foo" + +let gResult = g("foo"); +>gResult : "foo" +>g("foo") : "foo" +>g : (x: "foo") => "foo" +>"foo" : "foo" + +let h = bar(x => x); +>h : (x: "foo" | "bar") => "foo" | "bar" +>bar(x => x) : (x: "foo" | "bar") => "foo" | "bar" +>bar : (f: (x: T) => T) => (x: T) => T +>x => x : (x: "foo" | "bar") => "foo" | "bar" +>x : "foo" | "bar" +>x : "foo" | "bar" + +let hResult = h("foo"); +>hResult : "foo" | "bar" +>h("foo") : "foo" | "bar" +>h : (x: "foo" | "bar") => "foo" | "bar" +>"foo" : "foo" + +hResult = h("bar"); +>hResult = h("bar") : "foo" | "bar" +>hResult : "foo" | "bar" +>h("bar") : "foo" | "bar" +>h : (x: "foo" | "bar") => "foo" | "bar" +>"bar" : "bar" + diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt new file mode 100644 index 00000000000..ed6450ad329 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts(6,13): error TS2345: Argument of type '(y: "foo" | "bar") => string' is not assignable to parameter of type '(x: "foo") => "foo"'. + Type 'string' is not assignable to type '"foo"'. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTypeParameterConstraint02.ts (1 errors) ==== + + function foo(f: (x: T) => T) { + return f; + } + + let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(y: "foo" | "bar") => string' is not assignable to parameter of type '(x: "foo") => "foo"'. +!!! error TS2345: Type 'string' is not assignable to type '"foo"'. + let fResult = f("foo"); \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js new file mode 100644 index 00000000000..c024ac6bc43 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js @@ -0,0 +1,21 @@ +//// [stringLiteralTypesAsTypeParameterConstraint02.ts] + +function foo(f: (x: T) => T) { + return f; +} + +let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); +let fResult = f("foo"); + +//// [stringLiteralTypesAsTypeParameterConstraint02.js] +function foo(f) { + return f; +} +var f = foo(function (y) { return y === "foo" ? y : "foo"; }); +var fResult = f("foo"); + + +//// [stringLiteralTypesAsTypeParameterConstraint02.d.ts] +declare function foo(f: (x: T) => T): (x: T) => T; +declare let f: any; +declare let fResult: any; From b93394a7acc9b56cd9e97dccd311c2419762b76d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 10 Nov 2015 23:15:48 -0800 Subject: [PATCH 34/93] Added to comment. --- src/compiler/checker.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fe04cae13a..8f751f25523 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7114,9 +7114,16 @@ namespace ts { /** * Woah! Do you really want to use this function? * - * Unless you're trying to get the *non-apparent* type for a value-literal type, + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, * you probably meant to use 'getApparentTypeOfContextualType'. - * Otherwise this is slightly less useful. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContetxualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. * * @param node the expression whose contextual type will be returned. * @returns the contextual type of an expression. From e62603ba8522eca6529eccfd84480e8a1a4c7a6e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Nov 2015 08:51:37 -0800 Subject: [PATCH 35/93] Move export default check before module merge one As suggested by Anders. --- src/compiler/checker.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 05ced970793..2bbed26f23c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -486,10 +486,19 @@ namespace ts { if (location.kind === SyntaxKind.SourceFile || (location.kind === SyntaxKind.ModuleDeclaration && (location).name.kind === SyntaxKind.StringLiteral)) { - // It's an external module. Because of module/namespace merging, a module's exports are in scope, - // yet we never want to treat an export specifier as putting a member in scope, except 'default'. - // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope, - // unless it is 'default'. + // It's an external module. First see if the module has an export default and if the local + // name of that export default matches. + if (result = moduleExports["default"]) { + const localSymbol = getLocalSymbolForExportDefault(result); + if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { + break loop; + } + result = undefined; + } + + // Because of module/namespace merging, a module's exports are in scope, + // yet we never want to treat an export specifier as putting a member in scope. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope. // Two things to note about this: // 1. We have to check this without calling getSymbol. The problem with calling getSymbol // on an export specifier is that it might find the export specifier itself, and try to @@ -498,19 +507,11 @@ namespace ts { // 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely* // an alias. If we used &, we'd be throwing out symbols that have non alias aspects, // which is not the desired behavior. - const isLocalSymbolForExportDefault = doesNameResolveToLocalSymbolForExportDefault(moduleExports, meaning, name); if (hasProperty(moduleExports, name) && moduleExports[name].flags === SymbolFlags.Alias && - !isLocalSymbolForExportDefault && getDeclarationOfKind(moduleExports[name], SyntaxKind.ExportSpecifier)) { break; } - - if (isLocalSymbolForExportDefault) { - result = moduleExports["default"]; - break loop; - } - result = undefined; } if (result = getSymbol(moduleExports, name, meaning & SymbolFlags.ModuleMember)) { From b9778e6d20b9a96f40ece46d08d23df8cfc4c6bd Mon Sep 17 00:00:00 2001 From: zhengbli Date: Wed, 11 Nov 2015 10:31:09 -0800 Subject: [PATCH 36/93] 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 9472c0be9951bd2926d6e2200f8ce8c28da13dc4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Nov 2015 10:53:24 -0800 Subject: [PATCH 37/93] Remove now-unused function `doesNameResolveToLocalSymbolForExportDefault` is no longer used, so delete it. --- src/compiler/checker.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2bbed26f23c..175807ac686 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -677,12 +677,6 @@ namespace ts { return result; } - function doesNameResolveToLocalSymbolForExportDefault(exports: SymbolTable, meaning: SymbolFlags, name: string): boolean { - const defaultExport = exports["default"]; - const localSymbol = getLocalSymbolForExportDefault(defaultExport); - return defaultExport && (defaultExport.flags & meaning) && localSymbol && localSymbol.name === name; - } - function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); // Block-scoped variables cannot be used before their definition From 87230bcc1bb166fef8f22363f1695beaf5999dec Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 10:55:33 -0800 Subject: [PATCH 38/93] 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 5ea25ba9a09f5a9860b92093012a3cedd32bf664 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 10:57:32 -0800 Subject: [PATCH 39/93] remove whitespace --- src/harness/compilerRunner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 4a599e96812..011b10e4e6b 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -43,7 +43,7 @@ class CompilerBaselineRunner extends RunnerBase { private makeUnitName(name: string, root: string) { return ts.isRootedDiskPath(name) ? name : (root + name); }; - + public checkTestCodeOutput(fileName: string) { describe("compiler tests for " + fileName, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. From df1dd00f35542884a9fc85501c48d599b181ac82 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 12:19:47 -0800 Subject: [PATCH 40/93] 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 d3f338cb8b174ad43d5f1f8b32fb7fdbc843e5b9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 12:24:40 -0800 Subject: [PATCH 41/93] Updated LKG. --- lib/tsc.js | 3282 ++++++++++++++----------- lib/tsserver.js | 1614 ++++++++----- lib/typescript.d.ts | 19 +- lib/typescript.js | 4504 ++++++++++++++++++++--------------- lib/typescriptServices.d.ts | 19 +- lib/typescriptServices.js | 4504 ++++++++++++++++++++--------------- 6 files changed, 8034 insertions(+), 5908 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index bbbcedf0f47..87a413af729 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -665,7 +665,7 @@ var ts; } ts.fileExtensionIs = fileExtensionIs; ts.supportedExtensions = [".ts", ".tsx", ".d.ts"]; - ts.moduleFileExtensions = ts.supportedExtensions; + ts.supportedJsExtensions = ts.supportedExtensions.concat(".js", ".jsx"); function isSupportedSourceFileName(fileName) { if (!fileName) { return false; @@ -716,17 +716,16 @@ var ts; } function Signature(checker) { } + function Node(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0; + this.parent = undefined; + } ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0; - this.parent = undefined; - } - Node.prototype = { kind: kind }; - return Node; - }, + getNodeConstructor: function () { return Node; }, + getSourceFileConstructor: function () { return Node; }, getSymbolConstructor: function () { return Symbol; }, getTypeConstructor: function () { return Type; }, getSignatureConstructor: function () { return Signature; } @@ -1003,7 +1002,16 @@ var ts; if (writeByteOrderMark) { data = "\uFEFF" + data; } - _fs.writeFileSync(fileName, data, "utf8"); + var fd; + try { + fd = _fs.openSync(fileName, "w"); + _fs.writeSync(fd, data, undefined, "utf8"); + } + finally { + if (fd !== undefined) { + _fs.closeSync(fd); + } + } } function getCanonicalPath(path) { return useCaseSensitiveFileNames ? path.toLowerCase() : path; @@ -1688,6 +1696,7 @@ var ts; Disallow_inconsistently_cased_references_to_the_same_file: { code: 6078, category: ts.DiagnosticCategory.Message, key: "Disallow_inconsistently_cased_references_to_the_same_file_6078", message: "Disallow inconsistently-cased references to the same file." }, Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: ts.DiagnosticCategory.Message, key: "Specify_JSX_code_generation_Colon_preserve_or_react_6080", message: "Specify JSX code generation: 'preserve' or 'react'" }, Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: ts.DiagnosticCategory.Message, key: "Argument_for_jsx_must_be_preserve_or_react_6081", message: "Argument for '--jsx' must be 'preserve' or 'react'." }, + Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -2148,7 +2157,7 @@ var ts; function getCommentRanges(text, pos, trailing) { var result; var collecting = trailing || pos === 0; - while (true) { + while (pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13: @@ -2217,6 +2226,7 @@ var ts; } return result; } + return result; } function getLeadingCommentRanges(text, pos) { return getCommentRanges(text, pos, false); @@ -2312,7 +2322,7 @@ var ts; error(ts.Diagnostics.Digit_expected); } } - return +(text.substring(start, end)); + return "" + +(text.substring(start, end)); } function scanOctalDigits() { var start = pos; @@ -2704,7 +2714,7 @@ var ts; return pos++, token = 36; case 46: if (isDigit(text.charCodeAt(pos + 1))) { - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8; } if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) { @@ -2801,7 +2811,7 @@ var ts; case 55: case 56: case 57: - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8; case 58: return pos++, token = 54; @@ -3093,1034 +3103,6 @@ var ts; ts.createScanner = createScanner; })(ts || (ts = {})); var ts; -(function (ts) { - ts.bindTime = 0; - function or(state1, state2) { - return (state1 | state2) & 2 - ? 2 - : (state1 & state2) & 8 - ? 8 - : 4; - } - function getModuleInstanceState(node) { - if (node.kind === 215 || node.kind === 216) { - return 0; - } - else if (ts.isConstEnumDeclaration(node)) { - return 2; - } - else if ((node.kind === 222 || node.kind === 221) && !(node.flags & 2)) { - return 0; - } - else if (node.kind === 219) { - var state = 0; - ts.forEachChild(node, function (n) { - switch (getModuleInstanceState(n)) { - case 0: - return false; - case 2: - state = 2; - return false; - case 1: - state = 1; - return true; - } - }); - return state; - } - else if (node.kind === 218) { - return getModuleInstanceState(node.body); - } - else { - return 1; - } - } - ts.getModuleInstanceState = getModuleInstanceState; - var binder = createBinder(); - function bindSourceFile(file, options) { - var start = new Date().getTime(); - binder(file, options); - ts.bindTime += new Date().getTime() - start; - } - ts.bindSourceFile = bindSourceFile; - function createBinder() { - var file; - var options; - var parent; - var container; - var blockScopeContainer; - var lastContainer; - var seenThisKeyword; - var hasExplicitReturn; - var currentReachabilityState; - var labelStack; - var labelIndexMap; - var implicitLabels; - var inStrictMode; - var symbolCount = 0; - var Symbol; - var classifiableNames; - function bindSourceFile(f, opts) { - file = f; - options = opts; - inStrictMode = !!file.externalModuleIndicator; - classifiableNames = {}; - Symbol = ts.objectAllocator.getSymbolConstructor(); - if (!file.locals) { - bind(file); - file.symbolCount = symbolCount; - file.classifiableNames = classifiableNames; - } - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - seenThisKeyword = false; - hasExplicitReturn = false; - labelStack = undefined; - labelIndexMap = undefined; - implicitLabels = undefined; - } - return bindSourceFile; - function createSymbol(flags, name) { - symbolCount++; - return new Symbol(flags, name); - } - function addDeclarationToSymbol(symbol, node, symbolFlags) { - symbol.flags |= symbolFlags; - node.symbol = symbol; - if (!symbol.declarations) { - symbol.declarations = []; - } - symbol.declarations.push(node); - if (symbolFlags & 1952 && !symbol.exports) { - symbol.exports = {}; - } - if (symbolFlags & 6240 && !symbol.members) { - symbol.members = {}; - } - if (symbolFlags & 107455 && !symbol.valueDeclaration) { - symbol.valueDeclaration = node; - } - } - function getDeclarationName(node) { - if (node.name) { - if (node.kind === 218 && node.name.kind === 9) { - return "\"" + node.name.text + "\""; - } - if (node.name.kind === 136) { - var nameExpression = node.name.expression; - ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); - return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); - } - return node.name.text; - } - switch (node.kind) { - case 144: - return "__constructor"; - case 152: - case 147: - return "__call"; - case 153: - case 148: - return "__new"; - case 149: - return "__index"; - case 228: - return "__export"; - case 227: - return node.isExportEquals ? "export=" : "default"; - case 213: - case 214: - return node.flags & 512 ? "default" : undefined; - } - } - function getDisplayName(node) { - return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); - } - function declareSymbol(symbolTable, parent, node, includes, excludes) { - ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = node.flags & 512; - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); - var symbol; - if (name !== undefined) { - symbol = ts.hasProperty(symbolTable, name) - ? symbolTable[name] - : (symbolTable[name] = createSymbol(0, name)); - if (name && (includes & 788448)) { - classifiableNames[name] = name; - } - if (symbol.flags & excludes) { - if (node.name) { - node.name.parent = node; - } - var message = symbol.flags & 2 - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.flags & 512) { - message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); - ts.forEach(symbol.declarations, function (declaration) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); - }); - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); - symbol = createSymbol(0, name); - } - } - else { - symbol = createSymbol(0, "__missing"); - } - addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; - return symbol; - } - function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedNodeFlags(node) & 2; - if (symbolFlags & 8388608) { - if (node.kind === 230 || (node.kind === 221 && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - else { - if (hasExportModifier || container.flags & 131072) { - var exportKind = (symbolFlags & 107455 ? 1048576 : 0) | - (symbolFlags & 793056 ? 2097152 : 0) | - (symbolFlags & 1536 ? 4194304 : 0); - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - node.localSymbol = local; - return local; - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - } - function bindChildren(node) { - var saveParent = parent; - var saveContainer = container; - var savedBlockScopeContainer = blockScopeContainer; - parent = node; - var containerFlags = getContainerFlags(node); - if (containerFlags & 1) { - container = blockScopeContainer = node; - if (containerFlags & 4) { - container.locals = {}; - } - addToContainerChain(container); - } - else if (containerFlags & 2) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; - } - var savedReachabilityState; - var savedLabelStack; - var savedLabels; - var savedImplicitLabels; - var savedHasExplicitReturn; - var kind = node.kind; - var flags = node.flags; - flags &= ~1572864; - if (kind === 215) { - seenThisKeyword = false; - } - var saveState = kind === 248 || kind === 219 || ts.isFunctionLikeKind(kind); - if (saveState) { - savedReachabilityState = currentReachabilityState; - savedLabelStack = labelStack; - savedLabels = labelIndexMap; - savedImplicitLabels = implicitLabels; - savedHasExplicitReturn = hasExplicitReturn; - currentReachabilityState = 2; - hasExplicitReturn = false; - labelStack = labelIndexMap = implicitLabels = undefined; - } - bindReachableStatement(node); - if (currentReachabilityState === 2 && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { - flags |= 524288; - if (hasExplicitReturn) { - flags |= 1048576; - } - } - if (kind === 215) { - flags = seenThisKeyword ? flags | 262144 : flags & ~262144; - } - node.flags = flags; - if (saveState) { - hasExplicitReturn = savedHasExplicitReturn; - currentReachabilityState = savedReachabilityState; - labelStack = savedLabelStack; - labelIndexMap = savedLabels; - implicitLabels = savedImplicitLabels; - } - container = saveContainer; - parent = saveParent; - blockScopeContainer = savedBlockScopeContainer; - } - function bindReachableStatement(node) { - if (checkUnreachable(node)) { - ts.forEachChild(node, bind); - return; - } - switch (node.kind) { - case 198: - bindWhileStatement(node); - break; - case 197: - bindDoStatement(node); - break; - case 199: - bindForStatement(node); - break; - case 200: - case 201: - bindForInOrForOfStatement(node); - break; - case 196: - bindIfStatement(node); - break; - case 204: - case 208: - bindReturnOrThrow(node); - break; - case 203: - case 202: - bindBreakOrContinueStatement(node); - break; - case 209: - bindTryStatement(node); - break; - case 206: - bindSwitchStatement(node); - break; - case 220: - bindCaseBlock(node); - break; - case 207: - bindLabeledStatement(node); - break; - default: - ts.forEachChild(node, bind); - break; - } - } - function bindWhileStatement(n) { - var preWhileState = n.expression.kind === 84 ? 4 : currentReachabilityState; - var postWhileState = n.expression.kind === 99 ? 4 : currentReachabilityState; - bind(n.expression); - currentReachabilityState = preWhileState; - var postWhileLabel = pushImplicitLabel(); - bind(n.statement); - popImplicitLabel(postWhileLabel, postWhileState); - } - function bindDoStatement(n) { - var preDoState = currentReachabilityState; - var postDoLabel = pushImplicitLabel(); - bind(n.statement); - var postDoState = n.expression.kind === 99 ? 4 : preDoState; - popImplicitLabel(postDoLabel, postDoState); - bind(n.expression); - } - function bindForStatement(n) { - var preForState = currentReachabilityState; - var postForLabel = pushImplicitLabel(); - bind(n.initializer); - bind(n.condition); - bind(n.incrementor); - bind(n.statement); - var isInfiniteLoop = (!n.condition || n.condition.kind === 99); - var postForState = isInfiniteLoop ? 4 : preForState; - popImplicitLabel(postForLabel, postForState); - } - function bindForInOrForOfStatement(n) { - var preStatementState = currentReachabilityState; - var postStatementLabel = pushImplicitLabel(); - bind(n.initializer); - bind(n.expression); - bind(n.statement); - popImplicitLabel(postStatementLabel, preStatementState); - } - function bindIfStatement(n) { - var ifTrueState = n.expression.kind === 84 ? 4 : currentReachabilityState; - var ifFalseState = n.expression.kind === 99 ? 4 : currentReachabilityState; - currentReachabilityState = ifTrueState; - bind(n.expression); - bind(n.thenStatement); - if (n.elseStatement) { - var preElseState = currentReachabilityState; - currentReachabilityState = ifFalseState; - bind(n.elseStatement); - currentReachabilityState = or(currentReachabilityState, preElseState); - } - else { - currentReachabilityState = or(currentReachabilityState, ifFalseState); - } - } - function bindReturnOrThrow(n) { - bind(n.expression); - if (n.kind === 204) { - hasExplicitReturn = true; - } - currentReachabilityState = 4; - } - function bindBreakOrContinueStatement(n) { - bind(n.label); - var isValidJump = jumpToLabel(n.label, n.kind === 203 ? currentReachabilityState : 4); - if (isValidJump) { - currentReachabilityState = 4; - } - } - function bindTryStatement(n) { - var preTryState = currentReachabilityState; - bind(n.tryBlock); - var postTryState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.catchClause); - var postCatchState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.finallyBlock); - currentReachabilityState = or(postTryState, postCatchState); - } - function bindSwitchStatement(n) { - var preSwitchState = currentReachabilityState; - var postSwitchLabel = pushImplicitLabel(); - bind(n.expression); - bind(n.caseBlock); - var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242; }); - var postSwitchState = hasDefault && currentReachabilityState !== 2 ? 4 : preSwitchState; - popImplicitLabel(postSwitchLabel, postSwitchState); - } - function bindCaseBlock(n) { - var startState = currentReachabilityState; - for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { - var clause = _a[_i]; - currentReachabilityState = startState; - bind(clause); - if (clause.statements.length && currentReachabilityState === 2 && options.noFallthroughCasesInSwitch) { - errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); - } - } - } - function bindLabeledStatement(n) { - bind(n.label); - var ok = pushNamedLabel(n.label); - bind(n.statement); - if (ok) { - popNamedLabel(n.label, currentReachabilityState); - } - } - function getContainerFlags(node) { - switch (node.kind) { - case 186: - case 214: - case 215: - case 217: - case 155: - case 165: - return 1; - case 147: - case 148: - case 149: - case 143: - case 142: - case 213: - case 144: - case 145: - case 146: - case 152: - case 153: - case 173: - case 174: - case 218: - case 248: - case 216: - return 5; - case 244: - case 199: - case 200: - case 201: - case 220: - return 2; - case 192: - return ts.isFunctionLike(node.parent) ? 0 : 2; - } - return 0; - } - function addToContainerChain(next) { - if (lastContainer) { - lastContainer.nextContainer = next; - } - lastContainer = next; - } - function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { - declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); - } - function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { - switch (container.kind) { - case 218: - return declareModuleMember(node, symbolFlags, symbolExcludes); - case 248: - return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 186: - case 214: - return declareClassMember(node, symbolFlags, symbolExcludes); - case 217: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 155: - case 165: - case 215: - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 152: - case 153: - case 147: - case 148: - case 149: - case 143: - case 142: - case 144: - case 145: - case 146: - case 213: - case 173: - case 174: - case 216: - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function declareClassMember(node, symbolFlags, symbolExcludes) { - return node.flags & 64 - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - } - function declareSourceFileMember(node, symbolFlags, symbolExcludes) { - return ts.isExternalModule(file) - ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); - } - function hasExportDeclarations(node) { - var body = node.kind === 248 ? node : node.body; - if (body.kind === 248 || body.kind === 219) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var stat = _a[_i]; - if (stat.kind === 228 || stat.kind === 227) { - return true; - } - } - } - return false; - } - function setExportContextFlag(node) { - if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { - node.flags |= 131072; - } - else { - node.flags &= ~131072; - } - } - function bindModuleDeclaration(node) { - setExportContextFlag(node); - if (node.name.kind === 9) { - declareSymbolAndAddToSymbolTable(node, 512, 106639); - } - else { - var state = getModuleInstanceState(node); - if (state === 0) { - declareSymbolAndAddToSymbolTable(node, 1024, 0); - } - else { - declareSymbolAndAddToSymbolTable(node, 512, 106639); - if (node.symbol.flags & (16 | 32 | 256)) { - node.symbol.constEnumOnlyModule = false; - } - else { - var currentModuleIsConstEnumOnly = state === 2; - if (node.symbol.constEnumOnlyModule === undefined) { - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } - } - } - } - function bindFunctionOrConstructorType(node) { - var symbol = createSymbol(131072, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072); - var typeLiteralSymbol = createSymbol(2048, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048); - typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); - var _a; - } - function bindObjectLiteralExpression(node) { - if (inStrictMode) { - var seen = {}; - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - if (prop.name.kind !== 69) { - continue; - } - var identifier = prop.name; - var currentKind = prop.kind === 245 || prop.kind === 246 || prop.kind === 143 - ? 1 - : 2; - var existingKind = seen[identifier.text]; - if (!existingKind) { - seen[identifier.text] = currentKind; - continue; - } - if (currentKind === 1 && existingKind === 1) { - var span = ts.getErrorSpanForNode(file, identifier); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); - } - } - } - return bindAnonymousDeclaration(node, 4096, "__object"); - } - function bindAnonymousDeclaration(node, symbolFlags, name) { - var symbol = createSymbol(symbolFlags, name); - addDeclarationToSymbol(symbol, node, symbolFlags); - } - function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { - switch (blockScopeContainer.kind) { - case 218: - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - case 248: - if (ts.isExternalModule(container)) { - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - } - default: - if (!blockScopeContainer.locals) { - blockScopeContainer.locals = {}; - addToContainerChain(blockScopeContainer); - } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2, 107455); - } - function checkStrictModeIdentifier(node) { - if (inStrictMode && - node.originalKeywordKind >= 106 && - node.originalKeywordKind <= 114 && - !ts.isIdentifierName(node)) { - if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); - } - } - } - function getStrictModeIdentifierMessage(node) { - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; - } - function checkStrictModeBinaryExpression(node) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { - checkStrictModeEvalOrArguments(node, node.left); - } - } - function checkStrictModeCatchClause(node) { - if (inStrictMode && node.variableDeclaration) { - checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); - } - } - function checkStrictModeDeleteExpression(node) { - if (inStrictMode && node.expression.kind === 69) { - var span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); - } - } - function isEvalOrArgumentsIdentifier(node) { - return node.kind === 69 && - (node.text === "eval" || node.text === "arguments"); - } - function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 69) { - var identifier = name; - if (isEvalOrArgumentsIdentifier(identifier)) { - var span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); - } - } - } - function getStrictModeEvalOrArgumentsMessage(node) { - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; - } - function checkStrictModeFunctionName(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); - } - } - function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.flags & 32768) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); - } - } - function checkStrictModePostfixUnaryExpression(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - function checkStrictModePrefixUnaryExpression(node) { - if (inStrictMode) { - if (node.operator === 41 || node.operator === 42) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - } - function checkStrictModeWithStatement(node) { - if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); - } - } - function errorOnFirstToken(node, message, arg0, arg1, arg2) { - var span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); - } - function getDestructuringParameterName(node) { - return "__" + ts.indexOf(node.parent.parameters, node); - } - function bind(node) { - if (!node) { - return; - } - node.parent = parent; - var savedInStrictMode = inStrictMode; - if (!savedInStrictMode) { - updateStrictMode(node); - } - bindWorker(node); - bindChildren(node); - inStrictMode = savedInStrictMode; - } - function updateStrictMode(node) { - switch (node.kind) { - case 248: - case 219: - updateStrictModeStatementList(node.statements); - return; - case 192: - if (ts.isFunctionLike(node.parent)) { - updateStrictModeStatementList(node.statements); - } - return; - case 214: - case 186: - inStrictMode = true; - return; - } - } - function updateStrictModeStatementList(statements) { - for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { - var statement = statements_1[_i]; - if (!ts.isPrologueDirective(statement)) { - return; - } - if (isUseStrictPrologueDirective(statement)) { - inStrictMode = true; - return; - } - } - } - function isUseStrictPrologueDirective(node) { - var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); - return nodeText === "\"use strict\"" || nodeText === "'use strict'"; - } - function bindWorker(node) { - switch (node.kind) { - case 69: - return checkStrictModeIdentifier(node); - case 181: - return checkStrictModeBinaryExpression(node); - case 244: - return checkStrictModeCatchClause(node); - case 175: - return checkStrictModeDeleteExpression(node); - case 8: - return checkStrictModeNumericLiteral(node); - case 180: - return checkStrictModePostfixUnaryExpression(node); - case 179: - return checkStrictModePrefixUnaryExpression(node); - case 205: - return checkStrictModeWithStatement(node); - case 97: - seenThisKeyword = true; - return; - case 137: - return declareSymbolAndAddToSymbolTable(node, 262144, 530912); - case 138: - return bindParameter(node); - case 211: - case 163: - return bindVariableDeclarationOrBindingElement(node); - case 141: - case 140: - return bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 536870912 : 0), 107455); - case 245: - case 246: - return bindPropertyOrMethodOrAccessor(node, 4, 107455); - case 247: - return bindPropertyOrMethodOrAccessor(node, 8, 107455); - case 147: - case 148: - case 149: - return declareSymbolAndAddToSymbolTable(node, 131072, 0); - case 143: - case 142: - return bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 536870912 : 0), ts.isObjectLiteralMethod(node) ? 107455 : 99263); - case 213: - checkStrictModeFunctionName(node); - return declareSymbolAndAddToSymbolTable(node, 16, 106927); - case 144: - return declareSymbolAndAddToSymbolTable(node, 16384, 0); - case 145: - return bindPropertyOrMethodOrAccessor(node, 32768, 41919); - case 146: - return bindPropertyOrMethodOrAccessor(node, 65536, 74687); - case 152: - case 153: - return bindFunctionOrConstructorType(node); - case 155: - return bindAnonymousDeclaration(node, 2048, "__type"); - case 165: - return bindObjectLiteralExpression(node); - case 173: - case 174: - checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.text : "__function"; - return bindAnonymousDeclaration(node, 16, bindingName); - case 186: - case 214: - return bindClassLikeDeclaration(node); - case 215: - return bindBlockScopedDeclaration(node, 64, 792960); - case 216: - return bindBlockScopedDeclaration(node, 524288, 793056); - case 217: - return bindEnumDeclaration(node); - case 218: - return bindModuleDeclaration(node); - case 221: - case 224: - case 226: - case 230: - return declareSymbolAndAddToSymbolTable(node, 8388608, 8388608); - case 223: - return bindImportClause(node); - case 228: - return bindExportDeclaration(node); - case 227: - return bindExportAssignment(node); - case 248: - return bindSourceFileIfExternalModule(); - } - } - function bindSourceFileIfExternalModule() { - setExportContextFlag(file); - if (ts.isExternalModule(file)) { - bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); - } - } - function bindExportAssignment(node) { - if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 8388608, getDeclarationName(node)); - } - else if (node.expression.kind === 69) { - declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 107455 | 8388608); - } - else { - declareSymbol(container.symbol.exports, container.symbol, node, 4, 107455 | 8388608); - } - } - function bindExportDeclaration(node) { - if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 1073741824, getDeclarationName(node)); - } - else if (!node.exportClause) { - declareSymbol(container.symbol.exports, container.symbol, node, 1073741824, 0); - } - } - function bindImportClause(node) { - if (node.name) { - declareSymbolAndAddToSymbolTable(node, 8388608, 8388608); - } - } - function bindClassLikeDeclaration(node) { - if (node.kind === 214) { - bindBlockScopedDeclaration(node, 32, 899519); - } - else { - var bindingName = node.name ? node.name.text : "__class"; - bindAnonymousDeclaration(node, 32, bindingName); - if (node.name) { - classifiableNames[node.name.text] = node.name.text; - } - } - var symbol = node.symbol; - var prototypeSymbol = createSymbol(4 | 134217728, "prototype"); - if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { - if (node.name) { - node.name.parent = node; - } - file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); - } - symbol.exports[prototypeSymbol.name] = prototypeSymbol; - prototypeSymbol.parent = symbol; - } - function bindEnumDeclaration(node) { - return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128, 899967) - : bindBlockScopedDeclaration(node, 256, 899327); - } - function bindVariableDeclarationOrBindingElement(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); - } - if (!ts.isBindingPattern(node.name)) { - if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); - } - else if (ts.isParameterDeclaration(node)) { - declareSymbolAndAddToSymbolTable(node, 1, 107455); - } - else { - declareSymbolAndAddToSymbolTable(node, 1, 107454); - } - } - } - function bindParameter(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); - } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1, getDestructuringParameterName(node)); - } - else { - declareSymbolAndAddToSymbolTable(node, 1, 107455); - } - if (node.flags & 56 && - node.parent.kind === 144 && - ts.isClassLike(node.parent.parent)) { - var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4, 107455); - } - } - function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") - : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); - } - function pushNamedLabel(name) { - initializeReachabilityStateIfNecessary(); - if (ts.hasProperty(labelIndexMap, name.text)) { - return false; - } - labelIndexMap[name.text] = labelStack.push(1) - 1; - return true; - } - function pushImplicitLabel() { - initializeReachabilityStateIfNecessary(); - var index = labelStack.push(1) - 1; - implicitLabels.push(index); - return index; - } - function popNamedLabel(label, outerState) { - var index = labelIndexMap[label.text]; - ts.Debug.assert(index !== undefined); - ts.Debug.assert(labelStack.length == index + 1); - labelIndexMap[label.text] = undefined; - setCurrentStateAtLabel(labelStack.pop(), outerState, label); - } - function popImplicitLabel(implicitLabelIndex, outerState) { - if (labelStack.length !== implicitLabelIndex + 1) { - ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); - } - var i = implicitLabels.pop(); - if (implicitLabelIndex !== i) { - ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); - } - setCurrentStateAtLabel(labelStack.pop(), outerState, undefined); - } - function setCurrentStateAtLabel(innerMergedState, outerState, label) { - if (innerMergedState === 1) { - if (label && !options.allowUnusedLabels) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); - } - currentReachabilityState = outerState; - } - else { - currentReachabilityState = or(innerMergedState, outerState); - } - } - function jumpToLabel(label, outerState) { - initializeReachabilityStateIfNecessary(); - var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); - if (index === undefined) { - return false; - } - var stateAtLabel = labelStack[index]; - labelStack[index] = stateAtLabel === 1 ? outerState : or(stateAtLabel, outerState); - return true; - } - function checkUnreachable(node) { - switch (currentReachabilityState) { - case 4: - var reportError = ts.isStatement(node) || - node.kind === 214 || - (node.kind === 218 && shouldReportErrorOnModuleDeclaration(node)) || - (node.kind === 217 && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); - if (reportError) { - currentReachabilityState = 8; - var reportUnreachableCode = !options.allowUnreachableCode && - !ts.isInAmbientContext(node) && - (node.kind !== 193 || - ts.getCombinedNodeFlags(node.declarationList) & 24576 || - ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); - if (reportUnreachableCode) { - errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); - } - } - case 8: - return true; - default: - return false; - } - function shouldReportErrorOnModuleDeclaration(node) { - var instanceState = getModuleInstanceState(node); - return instanceState === 1 || (instanceState === 2 && options.preserveConstEnums); - } - } - function initializeReachabilityStateIfNecessary() { - if (labelIndexMap) { - return; - } - currentReachabilityState = 2; - labelIndexMap = {}; - labelStack = []; - implicitLabels = []; - } - } -})(ts || (ts = {})); -var ts; (function (ts) { function getDeclarationOfKind(symbol, kind) { var declarations = symbol.declarations; @@ -4396,6 +3378,10 @@ var ts; return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + function isExternalOrCommonJsModule(file) { + return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; + } + ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isDeclarationFile(file) { return (file.flags & 4096) !== 0; } @@ -4442,18 +3428,26 @@ var ts; return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; + function getLeadingCommentRangesOfNodeFromText(node, text) { + return ts.getLeadingCommentRanges(text, node.pos); + } + ts.getLeadingCommentRangesOfNodeFromText = getLeadingCommentRangesOfNodeFromText; function getJsDocComments(node, sourceFileOfNode) { - var commentRanges = (node.kind === 138 || node.kind === 137) ? - ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : - getLeadingCommentRangesOfNode(node, sourceFileOfNode); - return ts.filter(commentRanges, isJsDocComment); - function isJsDocComment(comment) { - return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 && - sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 && - sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47; - } + return getJsDocCommentsFromText(node, sourceFileOfNode.text); } ts.getJsDocComments = getJsDocComments; + function getJsDocCommentsFromText(node, text) { + var commentRanges = (node.kind === 138 || node.kind === 137) ? + ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : + getLeadingCommentRangesOfNodeFromText(node, text); + return ts.filter(commentRanges, isJsDocComment); + function isJsDocComment(comment) { + return text.charCodeAt(comment.pos + 1) === 42 && + text.charCodeAt(comment.pos + 2) === 42 && + text.charCodeAt(comment.pos + 3) !== 47; + } + } + ts.getJsDocCommentsFromText = getJsDocCommentsFromText; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; function isTypeNode(node) { @@ -4982,6 +3976,41 @@ var ts; return node.kind === 221 && node.moduleReference.kind !== 232; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; + function isSourceFileJavaScript(file) { + return isInJavaScriptFile(file); + } + ts.isSourceFileJavaScript = isSourceFileJavaScript; + function isInJavaScriptFile(node) { + return node && !!(node.parserContextFlags & 32); + } + ts.isInJavaScriptFile = isInJavaScriptFile; + function isRequireCall(expression) { + return expression.kind === 168 && + expression.expression.kind === 69 && + expression.expression.text === "require" && + expression.arguments.length === 1 && + expression.arguments[0].kind === 9; + } + ts.isRequireCall = isRequireCall; + function isExportsPropertyAssignment(expression) { + return isInJavaScriptFile(expression) && + (expression.kind === 181) && + (expression.operatorToken.kind === 56) && + (expression.left.kind === 166) && + (expression.left.expression.kind === 69) && + ((expression.left.expression).text === "exports"); + } + ts.isExportsPropertyAssignment = isExportsPropertyAssignment; + function isModuleExportsAssignment(expression) { + return isInJavaScriptFile(expression) && + (expression.kind === 181) && + (expression.operatorToken.kind === 56) && + (expression.left.kind === 166) && + (expression.left.expression.kind === 69) && + ((expression.left.expression).text === "module") && + (expression.left.name.text === "exports"); + } + ts.isModuleExportsAssignment = isModuleExportsAssignment; function getExternalModuleName(node) { if (node.kind === 222) { return node.moduleSpecifier; @@ -5293,8 +4322,8 @@ var ts; function getFileReferenceFromReferencePath(comment, commentRange) { var simpleReferenceRegEx = /^\/\/\/\s*/gim; - if (simpleReferenceRegEx.exec(comment)) { - if (isNoDefaultLibRegEx.exec(comment)) { + if (simpleReferenceRegEx.test(comment)) { + if (isNoDefaultLibRegEx.test(comment)) { return { isNoDefaultLib: true }; @@ -5336,12 +4365,20 @@ var ts; return isFunctionLike(node) && (node.flags & 256) !== 0 && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; + function isStringOrNumericLiteral(kind) { + return kind === 9 || kind === 8; + } + ts.isStringOrNumericLiteral = isStringOrNumericLiteral; function hasDynamicName(declaration) { - return declaration.name && - declaration.name.kind === 136 && - !isWellKnownSymbolSyntactically(declaration.name.expression); + return declaration.name && isDynamicName(declaration.name); } ts.hasDynamicName = hasDynamicName; + function isDynamicName(name) { + return name.kind === 136 && + !isStringOrNumericLiteral(name.expression.kind) && + !isWellKnownSymbolSyntactically(name.expression); + } + ts.isDynamicName = isDynamicName; function isWellKnownSymbolSyntactically(node) { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } @@ -5562,11 +4599,11 @@ var ts; } ts.getIndentSize = getIndentSize; function createTextWriter(newLine) { - var output = ""; - var indent = 0; - var lineStart = true; - var lineCount = 0; - var linePos = 0; + var output; + var indent; + var lineStart; + var lineCount; + var linePos; function write(s) { if (s && s.length) { if (lineStart) { @@ -5576,6 +4613,13 @@ var ts; output += s; } } + function reset() { + output = ""; + indent = 0; + lineStart = true; + lineCount = 0; + linePos = 0; + } function rawWrite(s) { if (s !== undefined) { if (lineStart) { @@ -5602,9 +4646,10 @@ var ts; lineStart = true; } } - function writeTextOfNode(sourceFile, node) { - write(getSourceTextOfNodeFromSourceFile(sourceFile, node)); + function writeTextOfNode(text, node) { + write(getTextOfNodeFromSourceText(text, node)); } + reset(); return { write: write, rawWrite: rawWrite, @@ -5617,10 +4662,17 @@ var ts; getTextPos: function () { return output.length; }, getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, - getText: function () { return output; } + getText: function () { return output; }, + reset: reset }; } ts.createTextWriter = createTextWriter; + function getExternalModuleNameFromPath(host, fileName) { + var dir = host.getCurrentDirectory(); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, fileName, dir, function (f) { return host.getCanonicalFileName(f); }, false); + return ts.removeFileExtension(relativePath); + } + ts.getExternalModuleNameFromPath = getExternalModuleNameFromPath; function getOwnEmitOutputFilePath(sourceFile, host, extension) { var compilerOptions = host.getCompilerOptions(); var emitOutputFilePathWithoutExtension; @@ -5649,6 +4701,10 @@ var ts; return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line; } ts.getLineOfLocalPosition = getLineOfLocalPosition; + function getLineOfLocalPositionFromLineMap(lineMap, pos) { + return ts.computeLineAndCharacterOfPosition(lineMap, pos).line; + } + ts.getLineOfLocalPositionFromLineMap = getLineOfLocalPositionFromLineMap; function getFirstConstructorWithBody(node) { return ts.forEach(node.members, function (member) { if (member.kind === 144 && nodeIsPresent(member.body)) { @@ -5719,21 +4775,21 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; - function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) { + function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) { + getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) { + function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { var emitLeadingSpace = !trailingSeparator; ts.forEach(comments, function (comment) { if (emitLeadingSpace) { writer.write(" "); emitLeadingSpace = false; } - writeComment(currentSourceFile, writer, comment, newLine); + writeComment(text, lineMap, writer, comment, newLine); if (comment.hasTrailingNewLine) { writer.writeLine(); } @@ -5746,16 +4802,16 @@ var ts; }); } ts.emitComments = emitComments; - function emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, removeComments) { + function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { if (node.pos === 0) { - leadingComments = ts.filter(ts.getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment); + leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedComment); } } else { - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { var detachedComments = []; @@ -5763,8 +4819,8 @@ var ts; for (var _i = 0, leadingComments_1 = leadingComments; _i < leadingComments_1.length; _i++) { var comment = leadingComments_1[_i]; if (lastComment) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end); - var commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); + var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { break; } @@ -5773,37 +4829,37 @@ var ts; lastComment = comment; } if (detachedComments.length) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, ts.lastOrUndefined(detachedComments).end); - var nodeLine = getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos)); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.lastOrUndefined(detachedComments).end); + var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { - emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - emitComments(currentSourceFile, writer, detachedComments, true, newLine, writeComment); + emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); + emitComments(text, lineMap, writer, detachedComments, true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } } return currentDetachedCommentInfo; function isPinnedComment(comment) { - return currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 33; + return text.charCodeAt(comment.pos + 1) === 42 && + text.charCodeAt(comment.pos + 2) === 33; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(currentSourceFile, writer, comment, newLine) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) { - var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos); - var lineCount = ts.getLineStarts(currentSourceFile).length; + function writeCommentRange(text, lineMap, writer, comment, newLine) { + if (text.charCodeAt(comment.pos + 1) === 42) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + var lineCount = lineMap.length; var firstCommentLineIndent; for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount - ? currentSourceFile.text.length + 1 - : getStartPositionOfLine(currentLine + 1, currentSourceFile); + ? text.length + 1 + : lineMap[currentLine + 1]; if (pos !== comment.pos) { if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); } var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); - var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart); + var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); @@ -5817,40 +4873,40 @@ var ts; writer.rawWrite(""); } } - writeTrimmedCurrentLine(pos, nextLineStart); + writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { - writer.write(currentSourceFile.text.substring(comment.pos, comment.end)); - } - function writeTrimmedCurrentLine(pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); - var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, ""); - if (currentLineText) { - writer.write(currentLineText); - if (end !== comment.end) { - writer.writeLine(); - } - } - else { - writer.writeLiteral(newLine); - } - } - function calculateIndent(pos, end) { - var currentLineIndent = 0; - for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) { - if (currentSourceFile.text.charCodeAt(pos) === 9) { - currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); - } - else { - currentLineIndent++; - } - } - return currentLineIndent; + writer.write(text.substring(comment.pos, comment.end)); } } ts.writeCommentRange = writeCommentRange; + function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { + var end = Math.min(comment.end, nextLineStart - 1); + var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); + if (currentLineText) { + writer.write(currentLineText); + if (end !== comment.end) { + writer.writeLine(); + } + } + else { + writer.writeLiteral(newLine); + } + } + function calculateIndent(text, pos, end) { + var currentLineIndent = 0; + for (; pos < end && ts.isWhiteSpace(text.charCodeAt(pos)); pos++) { + if (text.charCodeAt(pos) === 9) { + currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); + } + else { + currentLineIndent++; + } + } + return currentLineIndent; + } function modifierToFlag(token) { switch (token) { case 113: return 64; @@ -5944,14 +5000,14 @@ var ts; return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function isJavaScript(fileName) { - return ts.fileExtensionIs(fileName, ".js"); + function hasJavaScriptFileExtension(fileName) { + return ts.fileExtensionIs(fileName, ".js") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isJavaScript = isJavaScript; - function isTsx(fileName) { - return ts.fileExtensionIs(fileName, ".tsx"); + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function allowsJsxExpressions(fileName) { + return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isTsx = isTsx; + ts.allowsJsxExpressions = allowsJsxExpressions; function getExpandedCharCodes(input) { var output = []; var length = input.length; @@ -6161,14 +5217,16 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { - var nodeConstructors = new Array(272); ts.parseTime = 0; - function getNodeConstructor(kind) { - return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)); - } - ts.getNodeConstructor = getNodeConstructor; + var NodeConstructor; + var SourceFileConstructor; function createNode(kind, pos, end) { - return new (getNodeConstructor(kind))(pos, end); + if (kind === 248) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + } + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + } } ts.createNode = createNode; function visitNode(cbNode, node) { @@ -6567,6 +5625,8 @@ var ts; (function (Parser) { var scanner = ts.createScanner(2, true); var disallowInAndDecoratorContext = 1 | 4; + var NodeConstructor; + var SourceFileConstructor; var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -6579,13 +5639,16 @@ var ts; var contextFlags; var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); + var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; + initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; syntaxCursor = _syntaxCursor; parseDiagnostics = []; @@ -6593,12 +5656,12 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = ts.isJavaScript(fileName) ? 32 : 0; + contextFlags = isJavaScriptFile ? 32 : 0; parseErrorBeforeNextFinishedNode = false; scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(ts.isTsx(fileName) ? 1 : 0); + scanner.setLanguageVariant(ts.allowsJsxExpressions(fileName) ? 1 : 0); } function clearState() { scanner.setText(""); @@ -6611,6 +5674,9 @@ var ts; } function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { sourceFile = createSourceFile(fileName, languageVersion); + if (contextFlags & 32) { + sourceFile.parserContextFlags = 32; + } token = nextToken(); processReferenceComments(sourceFile); sourceFile.statements = parseList(0, parseStatement); @@ -6624,7 +5690,7 @@ var ts; if (setParentNodes) { fixupParentReferences(sourceFile); } - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { addJSDocComments(); } return sourceFile; @@ -6670,15 +5736,14 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion) { - var sourceFile = createNode(248, 0); - sourceFile.pos = 0; - sourceFile.end = sourceText.length; + var sourceFile = new SourceFileConstructor(248, 0, sourceText.length); + nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 : 0; - sourceFile.languageVariant = ts.isTsx(sourceFile.fileName) ? 1 : 0; + sourceFile.languageVariant = ts.allowsJsxExpressions(sourceFile.fileName) ? 1 : 0; return sourceFile; } function setContextFlag(val, flag) { @@ -6900,7 +5965,7 @@ var ts; if (!(pos >= 0)) { pos = scanner.getStartPos(); } - return new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))(pos, pos); + return new NodeConstructor(kind, pos, pos); } function finishNode(node, end) { node.end = end === undefined ? scanner.getStartPos() : end; @@ -7038,7 +6103,7 @@ var ts; case 12: return token === 19 || token === 37 || isLiteralPropertyName(); case 9: - return isLiteralPropertyName(); + return token === 19 || isLiteralPropertyName(); case 7: if (token === 15) { return lookAhead(isValidHeritageClauseObjectLiteral); @@ -7559,9 +6624,7 @@ var ts; } function parseParameterType() { if (parseOptional(54)) { - return token === 9 - ? parseLiteralNode(true) - : parseType(); + return parseType(); } return undefined; } @@ -7818,6 +6881,8 @@ var ts; case 131: var node = tryParse(parseKeywordAndNoDot); return node || parseTypeReferenceOrTypePredicate(); + case 9: + return parseLiteralNode(true); case 103: case 97: return parseTokenNode(); @@ -7847,6 +6912,7 @@ var ts; case 19: case 25: case 92: + case 9: return true; case 17: return lookAhead(isStartOfParenthesizedOrFunctionType); @@ -8360,7 +7426,6 @@ var ts; var unaryOperator = token; var simpleUnaryExpression = parseSimpleUnaryExpression(); if (token === 38) { - var diagnostic; var start = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); if (simpleUnaryExpression.kind === 171) { parseErrorAtPosition(start, simpleUnaryExpression.end - start, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); @@ -10024,7 +9089,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2, undefined); + initializeState("file.js", content, 2, true, undefined); var jsDocTypeExpression = parseJSDocTypeExpression(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -10275,7 +9340,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2, undefined); + initializeState("file.js", content, 2, true, undefined); var jsDocComment = parseJSDocComment(undefined, start, length); var diagnostics = parseDiagnostics; clearState(); @@ -10794,6 +9859,1075 @@ var ts; })(IncrementalParser || (IncrementalParser = {})); })(ts || (ts = {})); var ts; +(function (ts) { + ts.bindTime = 0; + function or(state1, state2) { + return (state1 | state2) & 2 + ? 2 + : (state1 & state2) & 8 + ? 8 + : 4; + } + function getModuleInstanceState(node) { + if (node.kind === 215 || node.kind === 216) { + return 0; + } + else if (ts.isConstEnumDeclaration(node)) { + return 2; + } + else if ((node.kind === 222 || node.kind === 221) && !(node.flags & 2)) { + return 0; + } + else if (node.kind === 219) { + var state = 0; + ts.forEachChild(node, function (n) { + switch (getModuleInstanceState(n)) { + case 0: + return false; + case 2: + state = 2; + return false; + case 1: + state = 1; + return true; + } + }); + return state; + } + else if (node.kind === 218) { + return getModuleInstanceState(node.body); + } + else { + return 1; + } + } + ts.getModuleInstanceState = getModuleInstanceState; + var binder = createBinder(); + function bindSourceFile(file, options) { + var start = new Date().getTime(); + binder(file, options); + ts.bindTime += new Date().getTime() - start; + } + ts.bindSourceFile = bindSourceFile; + function createBinder() { + var file; + var options; + var parent; + var container; + var blockScopeContainer; + var lastContainer; + var seenThisKeyword; + var hasExplicitReturn; + var currentReachabilityState; + var labelStack; + var labelIndexMap; + var implicitLabels; + var inStrictMode; + var symbolCount = 0; + var Symbol; + var classifiableNames; + function bindSourceFile(f, opts) { + file = f; + options = opts; + inStrictMode = !!file.externalModuleIndicator; + classifiableNames = {}; + Symbol = ts.objectAllocator.getSymbolConstructor(); + if (!file.locals) { + bind(file); + file.symbolCount = symbolCount; + file.classifiableNames = classifiableNames; + } + parent = undefined; + container = undefined; + blockScopeContainer = undefined; + lastContainer = undefined; + seenThisKeyword = false; + hasExplicitReturn = false; + labelStack = undefined; + labelIndexMap = undefined; + implicitLabels = undefined; + } + return bindSourceFile; + function createSymbol(flags, name) { + symbolCount++; + return new Symbol(flags, name); + } + function addDeclarationToSymbol(symbol, node, symbolFlags) { + symbol.flags |= symbolFlags; + node.symbol = symbol; + if (!symbol.declarations) { + symbol.declarations = []; + } + symbol.declarations.push(node); + if (symbolFlags & 1952 && !symbol.exports) { + symbol.exports = {}; + } + if (symbolFlags & 6240 && !symbol.members) { + symbol.members = {}; + } + if (symbolFlags & 107455 && !symbol.valueDeclaration) { + symbol.valueDeclaration = node; + } + } + function getDeclarationName(node) { + if (node.name) { + if (node.kind === 218 && node.name.kind === 9) { + return "\"" + node.name.text + "\""; + } + if (node.name.kind === 136) { + var nameExpression = node.name.expression; + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; + } + ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); + return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + } + return node.name.text; + } + switch (node.kind) { + case 144: + return "__constructor"; + case 152: + case 147: + return "__call"; + case 153: + case 148: + return "__new"; + case 149: + return "__index"; + case 228: + return "__export"; + case 227: + return node.isExportEquals ? "export=" : "default"; + case 181: + return "export="; + case 213: + case 214: + return node.flags & 512 ? "default" : undefined; + } + } + function getDisplayName(node) { + return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + } + function declareSymbol(symbolTable, parent, node, includes, excludes) { + ts.Debug.assert(!ts.hasDynamicName(node)); + var isDefaultExport = node.flags & 512; + var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var symbol; + if (name !== undefined) { + symbol = ts.hasProperty(symbolTable, name) + ? symbolTable[name] + : (symbolTable[name] = createSymbol(0, name)); + if (name && (includes & 788448)) { + classifiableNames[name] = name; + } + if (symbol.flags & excludes) { + if (node.name) { + node.name.parent = node; + } + var message = symbol.flags & 2 + ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : ts.Diagnostics.Duplicate_identifier_0; + ts.forEach(symbol.declarations, function (declaration) { + if (declaration.flags & 512) { + message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; + } + }); + ts.forEach(symbol.declarations, function (declaration) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); + }); + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); + symbol = createSymbol(0, name); + } + } + else { + symbol = createSymbol(0, "__missing"); + } + addDeclarationToSymbol(symbol, node, includes); + symbol.parent = parent; + return symbol; + } + function declareModuleMember(node, symbolFlags, symbolExcludes) { + var hasExportModifier = ts.getCombinedNodeFlags(node) & 2; + if (symbolFlags & 8388608) { + if (node.kind === 230 || (node.kind === 221 && hasExportModifier)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + else { + if (hasExportModifier || container.flags & 131072) { + var exportKind = (symbolFlags & 107455 ? 1048576 : 0) | + (symbolFlags & 793056 ? 2097152 : 0) | + (symbolFlags & 1536 ? 4194304 : 0); + var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + node.localSymbol = local; + return local; + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + } + function bindChildren(node) { + var saveParent = parent; + var saveContainer = container; + var savedBlockScopeContainer = blockScopeContainer; + parent = node; + var containerFlags = getContainerFlags(node); + if (containerFlags & 1) { + container = blockScopeContainer = node; + if (containerFlags & 4) { + container.locals = {}; + } + addToContainerChain(container); + } + else if (containerFlags & 2) { + blockScopeContainer = node; + blockScopeContainer.locals = undefined; + } + var savedReachabilityState; + var savedLabelStack; + var savedLabels; + var savedImplicitLabels; + var savedHasExplicitReturn; + var kind = node.kind; + var flags = node.flags; + flags &= ~1572864; + if (kind === 215) { + seenThisKeyword = false; + } + var saveState = kind === 248 || kind === 219 || ts.isFunctionLikeKind(kind); + if (saveState) { + savedReachabilityState = currentReachabilityState; + savedLabelStack = labelStack; + savedLabels = labelIndexMap; + savedImplicitLabels = implicitLabels; + savedHasExplicitReturn = hasExplicitReturn; + currentReachabilityState = 2; + hasExplicitReturn = false; + labelStack = labelIndexMap = implicitLabels = undefined; + } + bindReachableStatement(node); + if (currentReachabilityState === 2 && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { + flags |= 524288; + if (hasExplicitReturn) { + flags |= 1048576; + } + } + if (kind === 215) { + flags = seenThisKeyword ? flags | 262144 : flags & ~262144; + } + node.flags = flags; + if (saveState) { + hasExplicitReturn = savedHasExplicitReturn; + currentReachabilityState = savedReachabilityState; + labelStack = savedLabelStack; + labelIndexMap = savedLabels; + implicitLabels = savedImplicitLabels; + } + container = saveContainer; + parent = saveParent; + blockScopeContainer = savedBlockScopeContainer; + } + function bindReachableStatement(node) { + if (checkUnreachable(node)) { + ts.forEachChild(node, bind); + return; + } + switch (node.kind) { + case 198: + bindWhileStatement(node); + break; + case 197: + bindDoStatement(node); + break; + case 199: + bindForStatement(node); + break; + case 200: + case 201: + bindForInOrForOfStatement(node); + break; + case 196: + bindIfStatement(node); + break; + case 204: + case 208: + bindReturnOrThrow(node); + break; + case 203: + case 202: + bindBreakOrContinueStatement(node); + break; + case 209: + bindTryStatement(node); + break; + case 206: + bindSwitchStatement(node); + break; + case 220: + bindCaseBlock(node); + break; + case 207: + bindLabeledStatement(node); + break; + default: + ts.forEachChild(node, bind); + break; + } + } + function bindWhileStatement(n) { + var preWhileState = n.expression.kind === 84 ? 4 : currentReachabilityState; + var postWhileState = n.expression.kind === 99 ? 4 : currentReachabilityState; + bind(n.expression); + currentReachabilityState = preWhileState; + var postWhileLabel = pushImplicitLabel(); + bind(n.statement); + popImplicitLabel(postWhileLabel, postWhileState); + } + function bindDoStatement(n) { + var preDoState = currentReachabilityState; + var postDoLabel = pushImplicitLabel(); + bind(n.statement); + var postDoState = n.expression.kind === 99 ? 4 : preDoState; + popImplicitLabel(postDoLabel, postDoState); + bind(n.expression); + } + function bindForStatement(n) { + var preForState = currentReachabilityState; + var postForLabel = pushImplicitLabel(); + bind(n.initializer); + bind(n.condition); + bind(n.incrementor); + bind(n.statement); + var isInfiniteLoop = (!n.condition || n.condition.kind === 99); + var postForState = isInfiniteLoop ? 4 : preForState; + popImplicitLabel(postForLabel, postForState); + } + function bindForInOrForOfStatement(n) { + var preStatementState = currentReachabilityState; + var postStatementLabel = pushImplicitLabel(); + bind(n.initializer); + bind(n.expression); + bind(n.statement); + popImplicitLabel(postStatementLabel, preStatementState); + } + function bindIfStatement(n) { + var ifTrueState = n.expression.kind === 84 ? 4 : currentReachabilityState; + var ifFalseState = n.expression.kind === 99 ? 4 : currentReachabilityState; + currentReachabilityState = ifTrueState; + bind(n.expression); + bind(n.thenStatement); + if (n.elseStatement) { + var preElseState = currentReachabilityState; + currentReachabilityState = ifFalseState; + bind(n.elseStatement); + currentReachabilityState = or(currentReachabilityState, preElseState); + } + else { + currentReachabilityState = or(currentReachabilityState, ifFalseState); + } + } + function bindReturnOrThrow(n) { + bind(n.expression); + if (n.kind === 204) { + hasExplicitReturn = true; + } + currentReachabilityState = 4; + } + function bindBreakOrContinueStatement(n) { + bind(n.label); + var isValidJump = jumpToLabel(n.label, n.kind === 203 ? currentReachabilityState : 4); + if (isValidJump) { + currentReachabilityState = 4; + } + } + function bindTryStatement(n) { + var preTryState = currentReachabilityState; + bind(n.tryBlock); + var postTryState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.catchClause); + var postCatchState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.finallyBlock); + currentReachabilityState = or(postTryState, postCatchState); + } + function bindSwitchStatement(n) { + var preSwitchState = currentReachabilityState; + var postSwitchLabel = pushImplicitLabel(); + bind(n.expression); + bind(n.caseBlock); + var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242; }); + var postSwitchState = hasDefault && currentReachabilityState !== 2 ? 4 : preSwitchState; + popImplicitLabel(postSwitchLabel, postSwitchState); + } + function bindCaseBlock(n) { + var startState = currentReachabilityState; + for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { + var clause = _a[_i]; + currentReachabilityState = startState; + bind(clause); + if (clause.statements.length && currentReachabilityState === 2 && options.noFallthroughCasesInSwitch) { + errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); + } + } + } + function bindLabeledStatement(n) { + bind(n.label); + var ok = pushNamedLabel(n.label); + bind(n.statement); + if (ok) { + popNamedLabel(n.label, currentReachabilityState); + } + } + function getContainerFlags(node) { + switch (node.kind) { + case 186: + case 214: + case 215: + case 217: + case 155: + case 165: + return 1; + case 147: + case 148: + case 149: + case 143: + case 142: + case 213: + case 144: + case 145: + case 146: + case 152: + case 153: + case 173: + case 174: + case 218: + case 248: + case 216: + return 5; + case 244: + case 199: + case 200: + case 201: + case 220: + return 2; + case 192: + return ts.isFunctionLike(node.parent) ? 0 : 2; + } + return 0; + } + function addToContainerChain(next) { + if (lastContainer) { + lastContainer.nextContainer = next; + } + lastContainer = next; + } + function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { + declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); + } + function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { + switch (container.kind) { + case 218: + return declareModuleMember(node, symbolFlags, symbolExcludes); + case 248: + return declareSourceFileMember(node, symbolFlags, symbolExcludes); + case 186: + case 214: + return declareClassMember(node, symbolFlags, symbolExcludes); + case 217: + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + case 155: + case 165: + case 215: + return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + case 152: + case 153: + case 147: + case 148: + case 149: + case 143: + case 142: + case 144: + case 145: + case 146: + case 213: + case 173: + case 174: + case 216: + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function declareClassMember(node, symbolFlags, symbolExcludes) { + return node.flags & 64 + ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + } + function declareSourceFileMember(node, symbolFlags, symbolExcludes) { + return ts.isExternalModule(file) + ? declareModuleMember(node, symbolFlags, symbolExcludes) + : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + } + function hasExportDeclarations(node) { + var body = node.kind === 248 ? node : node.body; + if (body.kind === 248 || body.kind === 219) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var stat = _a[_i]; + if (stat.kind === 228 || stat.kind === 227) { + return true; + } + } + } + return false; + } + function setExportContextFlag(node) { + if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { + node.flags |= 131072; + } + else { + node.flags &= ~131072; + } + } + function bindModuleDeclaration(node) { + setExportContextFlag(node); + if (node.name.kind === 9) { + declareSymbolAndAddToSymbolTable(node, 512, 106639); + } + else { + var state = getModuleInstanceState(node); + if (state === 0) { + declareSymbolAndAddToSymbolTable(node, 1024, 0); + } + else { + declareSymbolAndAddToSymbolTable(node, 512, 106639); + if (node.symbol.flags & (16 | 32 | 256)) { + node.symbol.constEnumOnlyModule = false; + } + else { + var currentModuleIsConstEnumOnly = state === 2; + if (node.symbol.constEnumOnlyModule === undefined) { + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; + } + else { + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; + } + } + } + } + } + function bindFunctionOrConstructorType(node) { + var symbol = createSymbol(131072, getDeclarationName(node)); + addDeclarationToSymbol(symbol, node, 131072); + var typeLiteralSymbol = createSymbol(2048, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048); + typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); + var _a; + } + function bindObjectLiteralExpression(node) { + if (inStrictMode) { + var seen = {}; + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (prop.name.kind !== 69) { + continue; + } + var identifier = prop.name; + var currentKind = prop.kind === 245 || prop.kind === 246 || prop.kind === 143 + ? 1 + : 2; + var existingKind = seen[identifier.text]; + if (!existingKind) { + seen[identifier.text] = currentKind; + continue; + } + if (currentKind === 1 && existingKind === 1) { + var span = ts.getErrorSpanForNode(file, identifier); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); + } + } + } + return bindAnonymousDeclaration(node, 4096, "__object"); + } + function bindAnonymousDeclaration(node, symbolFlags, name) { + var symbol = createSymbol(symbolFlags, name); + addDeclarationToSymbol(symbol, node, symbolFlags); + } + function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { + switch (blockScopeContainer.kind) { + case 218: + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + case 248: + if (ts.isExternalModule(container)) { + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + } + default: + if (!blockScopeContainer.locals) { + blockScopeContainer.locals = {}; + addToContainerChain(blockScopeContainer); + } + declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function bindBlockScopedVariableDeclaration(node) { + bindBlockScopedDeclaration(node, 2, 107455); + } + function checkStrictModeIdentifier(node) { + if (inStrictMode && + node.originalKeywordKind >= 106 && + node.originalKeywordKind <= 114 && + !ts.isIdentifierName(node)) { + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + } + } + } + function getStrictModeIdentifierMessage(node) { + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node) { + if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + checkStrictModeEvalOrArguments(node, node.left); + } + } + function checkStrictModeCatchClause(node) { + if (inStrictMode && node.variableDeclaration) { + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); + } + } + function checkStrictModeDeleteExpression(node) { + if (inStrictMode && node.expression.kind === 69) { + var span = ts.getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); + } + } + function isEvalOrArgumentsIdentifier(node) { + return node.kind === 69 && + (node.text === "eval" || node.text === "arguments"); + } + function checkStrictModeEvalOrArguments(contextNode, name) { + if (name && name.kind === 69) { + var identifier = name; + if (isEvalOrArgumentsIdentifier(identifier)) { + var span = ts.getErrorSpanForNode(file, name); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + } + } + } + function getStrictModeEvalOrArgumentsMessage(node) { + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + } + function checkStrictModeFunctionName(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + } + function checkStrictModeNumericLiteral(node) { + if (inStrictMode && node.flags & 32768) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); + } + } + function checkStrictModePostfixUnaryExpression(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + function checkStrictModePrefixUnaryExpression(node) { + if (inStrictMode) { + if (node.operator === 41 || node.operator === 42) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + } + function checkStrictModeWithStatement(node) { + if (inStrictMode) { + errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + } + } + function errorOnFirstToken(node, message, arg0, arg1, arg2) { + var span = ts.getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + } + function getDestructuringParameterName(node) { + return "__" + ts.indexOf(node.parent.parameters, node); + } + function bind(node) { + if (!node) { + return; + } + node.parent = parent; + var savedInStrictMode = inStrictMode; + if (!savedInStrictMode) { + updateStrictMode(node); + } + bindWorker(node); + bindChildren(node); + inStrictMode = savedInStrictMode; + } + function updateStrictMode(node) { + switch (node.kind) { + case 248: + case 219: + updateStrictModeStatementList(node.statements); + return; + case 192: + if (ts.isFunctionLike(node.parent)) { + updateStrictModeStatementList(node.statements); + } + return; + case 214: + case 186: + inStrictMode = true; + return; + } + } + function updateStrictModeStatementList(statements) { + for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { + var statement = statements_1[_i]; + if (!ts.isPrologueDirective(statement)) { + return; + } + if (isUseStrictPrologueDirective(statement)) { + inStrictMode = true; + return; + } + } + } + function isUseStrictPrologueDirective(node) { + var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); + return nodeText === "\"use strict\"" || nodeText === "'use strict'"; + } + function bindWorker(node) { + switch (node.kind) { + case 69: + return checkStrictModeIdentifier(node); + case 181: + if (ts.isInJavaScriptFile(node)) { + if (ts.isExportsPropertyAssignment(node)) { + bindExportsPropertyAssignment(node); + } + else if (ts.isModuleExportsAssignment(node)) { + bindModuleExportsAssignment(node); + } + } + return checkStrictModeBinaryExpression(node); + case 244: + return checkStrictModeCatchClause(node); + case 175: + return checkStrictModeDeleteExpression(node); + case 8: + return checkStrictModeNumericLiteral(node); + case 180: + return checkStrictModePostfixUnaryExpression(node); + case 179: + return checkStrictModePrefixUnaryExpression(node); + case 205: + return checkStrictModeWithStatement(node); + case 97: + seenThisKeyword = true; + return; + case 137: + return declareSymbolAndAddToSymbolTable(node, 262144, 530912); + case 138: + return bindParameter(node); + case 211: + case 163: + return bindVariableDeclarationOrBindingElement(node); + case 141: + case 140: + return bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 536870912 : 0), 107455); + case 245: + case 246: + return bindPropertyOrMethodOrAccessor(node, 4, 107455); + case 247: + return bindPropertyOrMethodOrAccessor(node, 8, 107455); + case 147: + case 148: + case 149: + return declareSymbolAndAddToSymbolTable(node, 131072, 0); + case 143: + case 142: + return bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 536870912 : 0), ts.isObjectLiteralMethod(node) ? 107455 : 99263); + case 213: + checkStrictModeFunctionName(node); + return declareSymbolAndAddToSymbolTable(node, 16, 106927); + case 144: + return declareSymbolAndAddToSymbolTable(node, 16384, 0); + case 145: + return bindPropertyOrMethodOrAccessor(node, 32768, 41919); + case 146: + return bindPropertyOrMethodOrAccessor(node, 65536, 74687); + case 152: + case 153: + return bindFunctionOrConstructorType(node); + case 155: + return bindAnonymousDeclaration(node, 2048, "__type"); + case 165: + return bindObjectLiteralExpression(node); + case 173: + case 174: + checkStrictModeFunctionName(node); + var bindingName = node.name ? node.name.text : "__function"; + return bindAnonymousDeclaration(node, 16, bindingName); + case 168: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; + case 186: + case 214: + return bindClassLikeDeclaration(node); + case 215: + return bindBlockScopedDeclaration(node, 64, 792960); + case 216: + return bindBlockScopedDeclaration(node, 524288, 793056); + case 217: + return bindEnumDeclaration(node); + case 218: + return bindModuleDeclaration(node); + case 221: + case 224: + case 226: + case 230: + return declareSymbolAndAddToSymbolTable(node, 8388608, 8388608); + case 223: + return bindImportClause(node); + case 228: + return bindExportDeclaration(node); + case 227: + return bindExportAssignment(node); + case 248: + return bindSourceFileIfExternalModule(); + } + } + function bindSourceFileIfExternalModule() { + setExportContextFlag(file); + if (ts.isExternalModule(file)) { + bindSourceFileAsExternalModule(); + } + } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } + function bindExportAssignment(node) { + var boundExpression = node.kind === 227 ? node.expression : node.right; + if (!container.symbol || !container.symbol.exports) { + bindAnonymousDeclaration(node, 8388608, getDeclarationName(node)); + } + else if (boundExpression.kind === 69) { + declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 107455 | 8388608); + } + else { + declareSymbol(container.symbol.exports, container.symbol, node, 4, 107455 | 8388608); + } + } + function bindExportDeclaration(node) { + if (!container.symbol || !container.symbol.exports) { + bindAnonymousDeclaration(node, 1073741824, getDeclarationName(node)); + } + else if (!node.exportClause) { + declareSymbol(container.symbol.exports, container.symbol, node, 1073741824, 0); + } + } + function bindImportClause(node) { + if (node.name) { + declareSymbolAndAddToSymbolTable(node, 8388608, 8388608); + } + } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); + } + } + function bindExportsPropertyAssignment(node) { + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 | 7340032, 0); + } + function bindModuleExportsAssignment(node) { + setCommonJsModuleIndicator(node); + bindExportAssignment(node); + } + function bindCallExpression(node) { + if (!file.commonJsModuleIndicator && ts.isRequireCall(node)) { + setCommonJsModuleIndicator(node); + } + } + function bindClassLikeDeclaration(node) { + if (node.kind === 214) { + bindBlockScopedDeclaration(node, 32, 899519); + } + else { + var bindingName = node.name ? node.name.text : "__class"; + bindAnonymousDeclaration(node, 32, bindingName); + if (node.name) { + classifiableNames[node.name.text] = node.name.text; + } + } + var symbol = node.symbol; + var prototypeSymbol = createSymbol(4 | 134217728, "prototype"); + if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { + if (node.name) { + node.name.parent = node; + } + file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); + } + symbol.exports[prototypeSymbol.name] = prototypeSymbol; + prototypeSymbol.parent = symbol; + } + function bindEnumDeclaration(node) { + return ts.isConst(node) + ? bindBlockScopedDeclaration(node, 128, 899967) + : bindBlockScopedDeclaration(node, 256, 899327); + } + function bindVariableDeclarationOrBindingElement(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (!ts.isBindingPattern(node.name)) { + if (ts.isBlockOrCatchScoped(node)) { + bindBlockScopedVariableDeclaration(node); + } + else if (ts.isParameterDeclaration(node)) { + declareSymbolAndAddToSymbolTable(node, 1, 107455); + } + else { + declareSymbolAndAddToSymbolTable(node, 1, 107454); + } + } + } + function bindParameter(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (ts.isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, 1, getDestructuringParameterName(node)); + } + else { + declareSymbolAndAddToSymbolTable(node, 1, 107455); + } + if (node.flags & 56 && + node.parent.kind === 144 && + ts.isClassLike(node.parent.parent)) { + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4, 107455); + } + } + function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { + return ts.hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); + } + function pushNamedLabel(name) { + initializeReachabilityStateIfNecessary(); + if (ts.hasProperty(labelIndexMap, name.text)) { + return false; + } + labelIndexMap[name.text] = labelStack.push(1) - 1; + return true; + } + function pushImplicitLabel() { + initializeReachabilityStateIfNecessary(); + var index = labelStack.push(1) - 1; + implicitLabels.push(index); + return index; + } + function popNamedLabel(label, outerState) { + var index = labelIndexMap[label.text]; + ts.Debug.assert(index !== undefined); + ts.Debug.assert(labelStack.length == index + 1); + labelIndexMap[label.text] = undefined; + setCurrentStateAtLabel(labelStack.pop(), outerState, label); + } + function popImplicitLabel(implicitLabelIndex, outerState) { + if (labelStack.length !== implicitLabelIndex + 1) { + ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); + } + var i = implicitLabels.pop(); + if (implicitLabelIndex !== i) { + ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); + } + setCurrentStateAtLabel(labelStack.pop(), outerState, undefined); + } + function setCurrentStateAtLabel(innerMergedState, outerState, label) { + if (innerMergedState === 1) { + if (label && !options.allowUnusedLabels) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); + } + currentReachabilityState = outerState; + } + else { + currentReachabilityState = or(innerMergedState, outerState); + } + } + function jumpToLabel(label, outerState) { + initializeReachabilityStateIfNecessary(); + var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); + if (index === undefined) { + return false; + } + var stateAtLabel = labelStack[index]; + labelStack[index] = stateAtLabel === 1 ? outerState : or(stateAtLabel, outerState); + return true; + } + function checkUnreachable(node) { + switch (currentReachabilityState) { + case 4: + var reportError = (ts.isStatement(node) && node.kind !== 194) || + node.kind === 214 || + (node.kind === 218 && shouldReportErrorOnModuleDeclaration(node)) || + (node.kind === 217 && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + if (reportError) { + currentReachabilityState = 8; + var reportUnreachableCode = !options.allowUnreachableCode && + !ts.isInAmbientContext(node) && + (node.kind !== 193 || + ts.getCombinedNodeFlags(node.declarationList) & 24576 || + ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); + if (reportUnreachableCode) { + errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + } + } + case 8: + return true; + default: + return false; + } + function shouldReportErrorOnModuleDeclaration(node) { + var instanceState = getModuleInstanceState(node); + return instanceState === 1 || (instanceState === 2 && options.preserveConstEnums); + } + } + function initializeReachabilityStateIfNecessary() { + if (labelIndexMap) { + return; + } + currentReachabilityState = 2; + labelIndexMap = {}; + labelStack = []; + implicitLabels = []; + } + } +})(ts || (ts = {})); +var ts; (function (ts) { var nextSymbolId = 1; var nextNodeId = 1; @@ -10853,7 +10987,7 @@ var ts; symbolToString: symbolToString, getAugmentedPropertiesOfType: getAugmentedPropertiesOfType, getRootSymbols: getRootSymbols, - getContextualType: getContextualType, + getContextualType: getApparentTypeOfContextualType, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: getResolvedSignature, getConstantValue: getConstantValue, @@ -11109,7 +11243,7 @@ var ts; return ts.getAncestor(node, 248); } function isGlobalSourceFile(node) { - return node.kind === 248 && !ts.isExternalModule(node); + return node.kind === 248 && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning && ts.hasProperty(symbols, name)) { @@ -11195,23 +11329,24 @@ var ts; } switch (location.kind) { case 248: - if (!ts.isExternalModule(location)) + if (!ts.isExternalOrCommonJsModule(location)) break; case 218: var moduleExports = getSymbolOfNode(location).exports; if (location.kind === 248 || (location.kind === 218 && location.name.kind === 9)) { + if (result = moduleExports["default"]) { + var localSymbol = ts.getLocalSymbolForExportDefault(result); + if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { + break loop; + } + result = undefined; + } if (ts.hasProperty(moduleExports, name) && moduleExports[name].flags === 8388608 && ts.getDeclarationOfKind(moduleExports[name], 230)) { break; } - result = moduleExports["default"]; - var localSymbol = ts.getLocalSymbolForExportDefault(result); - if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) { - break loop; - } - result = undefined; } if (result = getSymbol(moduleExports, name, meaning & 8914931)) { break loop; @@ -11569,6 +11704,9 @@ var ts; if (moduleName === undefined) { return; } + if (moduleName.indexOf("!") >= 0) { + moduleName = moduleName.substr(0, moduleName.indexOf("!")); + } var isRelative = ts.isExternalModuleNameRelative(moduleName); if (!isRelative) { var symbol = getSymbol(globals, "\"" + moduleName + "\"", 512); @@ -11739,7 +11877,7 @@ var ts; } switch (location_1.kind) { case 248: - if (!ts.isExternalModule(location_1)) { + if (!ts.isExternalOrCommonJsModule(location_1)) { break; } case 218: @@ -11866,7 +12004,7 @@ var ts; } function hasExternalModuleSymbol(declaration) { return (declaration.kind === 218 && declaration.name.kind === 9) || - (declaration.kind === 248 && ts.isExternalModule(declaration)); + (declaration.kind === 248 && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol) { var aliasesToMakeVisible; @@ -12064,7 +12202,7 @@ var ts; writeAnonymousType(type, flags); } else if (type.flags & 256) { - writer.writeStringLiteral(type.text); + writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); } else { writePunctuation(writer, 15); @@ -12428,7 +12566,7 @@ var ts; } } else if (node.kind === 248) { - return ts.isExternalModule(node) ? node : undefined; + return ts.isExternalOrCommonJsModule(node) ? node : undefined; } } ts.Debug.fail("getContainingModule cant reach here"); @@ -12633,6 +12771,23 @@ var ts; var symbol = getSymbolOfNode(node); return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node); } + function getTextOfPropertyName(name) { + switch (name.kind) { + case 69: + return name.text; + case 9: + case 8: + return name.text; + case 136: + if (ts.isStringOrNumericLiteral(name.expression.kind)) { + return name.expression.text; + } + } + return undefined; + } + function isComputedNonLiteralName(name) { + return name.kind === 136 && !ts.isStringOrNumericLiteral(name.expression.kind); + } function getTypeForBindingElement(declaration) { var pattern = declaration.parent; var parentType = getTypeForBindingElementParent(pattern.parent); @@ -12648,8 +12803,12 @@ var ts; var type; if (pattern.kind === 161) { var name_10 = declaration.propertyName || declaration.name; - type = getTypeOfPropertyOfType(parentType, name_10.text) || - isNumericLiteralName(name_10.text) && getIndexTypeOfType(parentType, 1) || + if (isComputedNonLiteralName(name_10)) { + return anyType; + } + var text = getTextOfPropertyName(name_10); + type = getTypeOfPropertyOfType(parentType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1) || getIndexTypeOfType(parentType, 0); if (!type) { error(name_10, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_10)); @@ -12727,10 +12886,16 @@ var ts; } function getTypeFromObjectBindingPattern(pattern, includePatternInType) { var members = {}; + var hasComputedProperties = false; ts.forEach(pattern.elements, function (e) { - var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0); var name = e.propertyName || e.name; - var symbol = createSymbol(flags, name.text); + if (isComputedNonLiteralName(name)) { + hasComputedProperties = true; + return; + } + var text = getTextOfPropertyName(name); + var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0); + var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType); symbol.bindingElement = e; members[symbol.name] = symbol; @@ -12739,6 +12904,9 @@ var ts; if (includePatternInType) { result.pattern = pattern; } + if (hasComputedProperties) { + result.flags |= 67108864; + } return result; } function getTypeFromArrayBindingPattern(pattern, includePatternInType) { @@ -12789,6 +12957,12 @@ var ts; if (declaration.kind === 227) { return links.type = checkExpression(declaration.expression); } + if (declaration.kind === 181) { + return links.type = checkExpression(declaration.right); + } + if (declaration.kind === 166) { + return checkExpressionCached(declaration.parent.right); + } if (!pushTypeResolution(symbol, 0)) { return unknownType; } @@ -13038,17 +13212,19 @@ var ts; } function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - var baseContructorType = getBaseConstructorTypeOfClass(type); - if (!(baseContructorType.flags & 80896)) { + var baseConstructorType = getBaseConstructorTypeOfClass(type); + if (!(baseConstructorType.flags & 80896)) { return; } var baseTypeNode = getBaseTypeNodeOfClass(type); var baseType; - if (baseContructorType.symbol && baseContructorType.symbol.flags & 32) { - baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol); + var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 && + areAllOuterTypeParametersApplied(originalBaseType)) { + baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } else { - var constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments); + var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); return; @@ -13073,6 +13249,15 @@ var ts; type.resolvedBaseTypes.push(baseType); } } + function areAllOuterTypeParametersApplied(type) { + var outerTypeParameters = type.outerTypeParameters; + if (outerTypeParameters) { + var last = outerTypeParameters.length - 1; + var typeArguments = type.typeArguments; + return outerTypeParameters[last].symbol !== typeArguments[last].symbol; + } + return true; + } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { @@ -13144,7 +13329,7 @@ var ts; type.typeArguments = type.typeParameters; type.thisType = createType(512 | 33554432); type.thisType.symbol = symbol; - type.thisType.constraint = getTypeWithThisArgument(type); + type.thisType.constraint = type; } } return links.declaredType; @@ -13619,14 +13804,19 @@ var ts; type = getApparentType(type); return type.flags & 49152 ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } + function getApparentTypeOfTypeParameter(type) { + if (!type.resolvedApparentType) { + var constraintType = getConstraintOfTypeParameter(type); + while (constraintType && constraintType.flags & 512) { + constraintType = getConstraintOfTypeParameter(constraintType); + } + type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type); + } + return type.resolvedApparentType; + } function getApparentType(type) { if (type.flags & 512) { - do { - type = getConstraintOfTypeParameter(type); - } while (type && type.flags & 512); - if (!type) { - type = emptyObjectType; - } + type = getApparentTypeOfTypeParameter(type); } if (type.flags & 258) { type = globalStringType; @@ -13779,7 +13969,7 @@ var ts; if (node.initializer) { var signatureDeclaration = node.parent; var signature = getSignatureFromDeclaration(signatureDeclaration); - var parameterIndex = signatureDeclaration.parameters.indexOf(node); + var parameterIndex = ts.indexOf(signatureDeclaration.parameters, node); ts.Debug.assert(parameterIndex >= 0); return parameterIndex >= signature.minArgumentCount; } @@ -13874,6 +14064,16 @@ var ts; } return result; } + function resolveExternalModuleTypeByLiteral(name) { + var moduleSym = resolveExternalModuleName(name, name); + if (moduleSym) { + var resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + return getTypeOfSymbol(resolvedModuleSymbol); + } + } + return anyType; + } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { if (!pushTypeResolution(signature, 3)) { @@ -14335,11 +14535,12 @@ var ts; return links.resolvedType; } function getStringLiteralType(node) { - if (ts.hasProperty(stringLiteralTypes, node.text)) { - return stringLiteralTypes[node.text]; + var text = node.text; + if (ts.hasProperty(stringLiteralTypes, text)) { + return stringLiteralTypes[text]; } - var type = stringLiteralTypes[node.text] = createType(256); - type.text = ts.getTextOfNode(node); + var type = stringLiteralTypes[text] = createType(256); + type.text = text; return type; } function getTypeFromStringLiteral(node) { @@ -14808,7 +15009,7 @@ var ts; return false; } function hasExcessProperties(source, target, reportErrors) { - if (someConstituentTypeHasKind(target, 80896)) { + if (!(target.flags & 67108864) && someConstituentTypeHasKind(target, 80896)) { for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (!isKnownProperty(target, prop.name)) { @@ -14898,9 +15099,6 @@ var ts; return result; } function typeParameterIdenticalTo(source, target) { - if (source.symbol.name !== target.symbol.name) { - return 0; - } if (source.constraint === target.constraint) { return -1; } @@ -15345,18 +15543,24 @@ var ts; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } + function isMatchingSignature(source, target, partialMatch) { + if (source.parameters.length === target.parameters.length && + source.minArgumentCount === target.minArgumentCount && + source.hasRestParameter === target.hasRestParameter) { + return true; + } + if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (source.hasRestParameter && !target.hasRestParameter || + source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) { + return true; + } + return false; + } function compareSignatures(source, target, partialMatch, ignoreReturnTypes, compareTypes) { if (source === target) { return -1; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { - if (!partialMatch || - source.parameters.length < target.parameters.length && !source.hasRestParameter || - source.minArgumentCount > target.minArgumentCount) { - return 0; - } + if (!(isMatchingSignature(source, target, partialMatch))) { + return 0; } var result = -1; if (source.typeParameters && target.typeParameters) { @@ -15441,6 +15645,9 @@ var ts; function isTupleLikeType(type) { return !!getPropertyOfType(type, "0"); } + function isStringLiteralType(type) { + return type.flags & 256; + } function isTupleType(type) { return !!(type.flags & 8192); } @@ -16032,7 +16239,7 @@ var ts; } } function narrowTypeByInstanceof(type, expr, assumeTrue) { - if (isTypeAny(type) || !assumeTrue || expr.left.kind !== 69 || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || expr.left.kind !== 69 || getResolvedSymbol(expr.left) !== symbol) { return type; } var rightType = checkExpression(expr.right); @@ -16060,6 +16267,12 @@ var ts; } } if (targetType) { + if (!assumeTrue) { + if (type.flags & 16384) { + return getUnionType(ts.filter(type.types, function (t) { return !isTypeSubtypeOf(t, targetType); })); + } + return type; + } return getNarrowedType(type, targetType); } return type; @@ -16471,6 +16684,9 @@ var ts; function getIndexTypeOfContextualType(type, kind) { return applyToContextualType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }); } + function contextualTypeIsStringLiteralType(type) { + return !!(type.flags & 16384 ? ts.forEach(type.types, isStringLiteralType) : isStringLiteralType(type)); + } function contextualTypeIsTupleLikeType(type) { return !!(type.flags & 16384 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); } @@ -16486,7 +16702,7 @@ var ts; } function getContextualTypeForObjectLiteralElement(element) { var objectLiteral = element.parent; - var type = getContextualType(objectLiteral); + var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!ts.hasDynamicName(element)) { var symbolName = getSymbolOfNode(element).name; @@ -16502,7 +16718,7 @@ var ts; } function getContextualTypeForElementExpression(node) { var arrayLiteral = node.parent; - var type = getContextualType(arrayLiteral); + var type = getApparentTypeOfContextualType(arrayLiteral); if (type) { var index = ts.indexOf(arrayLiteral.elements, node); return getTypeOfPropertyOfContextualType(type, "" + index) @@ -16531,11 +16747,11 @@ var ts; } return undefined; } - function getContextualType(node) { - var type = getContextualTypeWorker(node); + function getApparentTypeOfContextualType(node) { + var type = getContextualType(node); return type && getApparentType(type); } - function getContextualTypeWorker(node) { + function getContextualType(node) { if (isInsideWithStatementBody(node)) { return undefined; } @@ -16601,7 +16817,7 @@ var ts; ts.Debug.assert(node.kind !== 143 || ts.isObjectLiteralMethod(node)); var type = ts.isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node) - : getContextualType(node); + : getApparentTypeOfContextualType(node); if (!type) { return undefined; } @@ -16684,7 +16900,7 @@ var ts; type.pattern = node; return type; } - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; if (pattern && (pattern.kind === 162 || pattern.kind === 164)) { @@ -16739,10 +16955,11 @@ var ts; checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable = {}; var propertiesArray = []; - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === 161 || contextualType.pattern.kind === 165); var typeFlags = 0; + var patternWithComputedProperties = false; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var memberDecl = _a[_i]; var member = memberDecl.symbol; @@ -16768,8 +16985,11 @@ var ts; if (isOptional) { prop.flags |= 536870912; } + if (ts.hasDynamicName(memberDecl)) { + patternWithComputedProperties = true; + } } - else if (contextualTypeHasPattern) { + else if (contextualTypeHasPattern && !(contextualType.flags & 67108864)) { var impliedProp = getPropertyOfType(contextualType, member.name); if (impliedProp) { prop.flags |= impliedProp.flags & 536870912; @@ -16812,7 +17032,7 @@ var ts; var numberIndexType = getIndexType(1); var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType); var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 1048576; - result.flags |= 524288 | 4194304 | freshObjectLiteralFlag | (typeFlags & 14680064); + result.flags |= 524288 | 4194304 | freshObjectLiteralFlag | (typeFlags & 14680064) | (patternWithComputedProperties ? 67108864 : 0); if (inDestructuringPattern) { result.pattern = node; } @@ -18027,6 +18247,9 @@ var ts; return anyType; } } + if (ts.isInJavaScriptFile(node) && ts.isRequireCall(node)) { + return resolveExternalModuleTypeByLiteral(node.arguments[0]); + } return getReturnTypeOfSignature(signature); } function checkTaggedTemplateExpression(node) { @@ -18037,7 +18260,9 @@ var ts; var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { var widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { + var bothAreStringLike = someConstituentTypeHasKind(targetType, 258) && + someConstituentTypeHasKind(widenedType, 258); + if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } @@ -18476,17 +18701,24 @@ var ts; var p = properties_3[_i]; if (p.kind === 245 || p.kind === 246) { var name_13 = p.name; + if (name_13.kind === 136) { + checkComputedPropertyName(name_13); + } + if (isComputedNonLiteralName(name_13)) { + continue; + } + var text = getTextOfPropertyName(name_13); var type = isTypeAny(sourceType) ? sourceType - : getTypeOfPropertyOfType(sourceType, name_13.text) || - isNumericLiteralName(name_13.text) && getIndexTypeOfType(sourceType, 1) || + : getTypeOfPropertyOfType(sourceType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(sourceType, 1) || getIndexTypeOfType(sourceType, 0); if (type) { if (p.kind === 246) { checkDestructuringAssignment(p, type); } else { - checkDestructuringAssignment(p.initializer || name_13, type); + checkDestructuringAssignment(p.initializer, type); } } else { @@ -18664,6 +18896,9 @@ var ts; case 31: case 32: case 33: + if (someConstituentTypeHasKind(leftType, 258) && someConstituentTypeHasKind(rightType, 258)) { + return booleanType; + } if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { reportOperatorError(); } @@ -18771,6 +19006,13 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getUnionType([type1, type2]); } + function checkStringLiteralExpression(node) { + var contextualType = getContextualType(node); + if (contextualType && contextualTypeIsStringLiteralType(contextualType)) { + return getStringLiteralType(node); + } + return stringType; + } function checkTemplateExpression(node) { ts.forEach(node.templateSpans, function (templateSpan) { checkExpression(templateSpan.expression); @@ -18809,7 +19051,7 @@ var ts; if (isInferentialContext(contextualMapper)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(contextualType); if (contextualSignature && !contextualSignature.typeParameters) { @@ -18861,6 +19103,7 @@ var ts; case 183: return checkTemplateExpression(node); case 9: + return checkStringLiteralExpression(node); case 11: return stringType; case 10: @@ -19922,7 +20165,7 @@ var ts; return; } var parent = getDeclarationContainer(node); - if (parent.kind === 248 && ts.isExternalModule(parent)) { + if (parent.kind === 248 && ts.isExternalOrCommonJsModule(parent)) { error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } @@ -19993,6 +20236,11 @@ var ts; checkExpressionCached(node.initializer); } } + if (node.kind === 163) { + if (node.propertyName && node.propertyName.kind === 136) { + checkComputedPropertyName(node.propertyName); + } + } if (ts.isBindingPattern(node.name)) { ts.forEach(node.name.elements, checkSourceElement); } @@ -20351,6 +20599,7 @@ var ts; var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); + var expressionTypeIsStringLike = someConstituentTypeHasKind(expressionType, 258); ts.forEach(node.caseBlock.clauses, function (clause) { if (clause.kind === 242 && !hasDuplicateDefaultClause) { if (firstDefaultClause === undefined) { @@ -20367,6 +20616,9 @@ var ts; if (produceDiagnostics && clause.kind === 241) { var caseClause = clause; var caseType = checkExpression(caseClause.expression); + if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, 258)) { + return; + } if (!isTypeAssignableTo(expressionType, caseType)) { checkTypeAssignableTo(caseType, expressionType, caseClause.expression, undefined); } @@ -20774,11 +21026,14 @@ var ts; var enumIsConst = ts.isConst(node); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.name.kind === 136) { + if (isComputedNonLiteralName(member.name)) { error(member.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums); } - else if (isNumericLiteralName(member.name.text)) { - error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + else { + var text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text)) { + error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + } } var previousEnumMemberIsNonConstant = autoValue === undefined; var initializer = member.initializer; @@ -21476,8 +21731,10 @@ var ts; function checkSourceFileWorker(node) { var links = getNodeLinks(node); if (!(links.flags & 1)) { - if (node.isDefaultLib && compilerOptions.skipDefaultLibCheck) { - return; + if (compilerOptions.skipDefaultLibCheck) { + if (node.hasNoDefaultLib) { + return; + } } checkGrammarSourceFile(node); emitExtends = false; @@ -21486,7 +21743,7 @@ var ts; potentialThisCollisions.length = 0; ts.forEach(node.statements, checkSourceElement); checkFunctionAndClassExpressionBodies(node); - if (ts.isExternalModule(node)) { + if (ts.isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); } if (potentialThisCollisions.length) { @@ -21564,7 +21821,7 @@ var ts; } switch (location.kind) { case 248: - if (!ts.isExternalModule(location)) { + if (!ts.isExternalOrCommonJsModule(location)) { break; } case 218: @@ -22123,15 +22380,24 @@ var ts; getReferencedValueDeclaration: getReferencedValueDeclaration, getTypeReferenceSerializationKind: getTypeReferenceSerializationKind, isOptionalParameter: isOptionalParameter, - isArgumentsLocalBinding: isArgumentsLocalBinding + isArgumentsLocalBinding: isArgumentsLocalBinding, + getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration }; } + function getExternalModuleFileFromDeclaration(declaration) { + var specifier = ts.getExternalModuleName(declaration); + var moduleSymbol = getSymbolAtLocation(specifier); + if (!moduleSymbol) { + return undefined; + } + return ts.getDeclarationOfKind(moduleSymbol, 248); + } function initializeTypeChecker() { ts.forEach(host.getSourceFiles(), function (file) { ts.bindSourceFile(file, compilerOptions); }); ts.forEach(host.getSourceFiles(), function (file) { - if (!ts.isExternalModule(file)) { + if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } }); @@ -22808,7 +23074,7 @@ var ts; } } function checkGrammarForNonSymbolComputedProperty(node, message) { - if (node.kind === 136 && !ts.isWellKnownSymbolSyntactically(node.expression)) { + if (ts.isDynamicName(node)) { return grammarErrorOnNode(node, message); } } @@ -23122,11 +23388,15 @@ var ts; var writeTextOfNode; var writer = createAndSetNewTextWriterWithSymbolWriter(); var enclosingDeclaration; - var currentSourceFile; + var currentText; + var currentLineMap; + var currentIdentifiers; + var isCurrentFileExternalModule; var reportedDeclarationError = false; var errorNameNode; var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments; var emit = compilerOptions.stripInternal ? stripInternal : emitNode; + var noDeclare = !root; var moduleElementDeclarationEmitInfo = []; var asynchronousSubModuleDeclarationEmitInfo; var referencePathsOutput = ""; @@ -23162,21 +23432,53 @@ var ts; } else { var emittedReferencedFiles = []; + var prevModuleElementDeclarationEmitInfo = []; ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + if (!ts.isDeclarationFile(sourceFile)) { if (!compilerOptions.noResolve) { ts.forEach(sourceFile.referencedFiles, function (fileReference) { var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference); - if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) && + if (referencedFile && (ts.isDeclarationFile(referencedFile) && !ts.contains(emittedReferencedFiles, referencedFile))) { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); } }); } + } + if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + noDeclare = false; emitSourceFile(sourceFile); } + else if (ts.isExternalModule(sourceFile)) { + noDeclare = true; + write("declare module \"" + ts.getResolvedExternalModuleName(host, sourceFile) + "\" {"); + writeLine(); + increaseIndent(); + emitSourceFile(sourceFile); + decreaseIndent(); + write("}"); + writeLine(); + if (moduleElementDeclarationEmitInfo.length) { + var oldWriter = writer; + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.isVisible && !aliasEmitInfo.asynchronousOutput) { + ts.Debug.assert(aliasEmitInfo.node.kind === 222); + createAndSetNewTextWriterWithSymbolWriter(); + ts.Debug.assert(aliasEmitInfo.indent === 1); + increaseIndent(); + writeImportDeclaration(aliasEmitInfo.node); + aliasEmitInfo.asynchronousOutput = writer.getText(); + decreaseIndent(); + } + }); + setWriter(oldWriter); + } + prevModuleElementDeclarationEmitInfo = prevModuleElementDeclarationEmitInfo.concat(moduleElementDeclarationEmitInfo); + moduleElementDeclarationEmitInfo = []; + } }); + moduleElementDeclarationEmitInfo = moduleElementDeclarationEmitInfo.concat(prevModuleElementDeclarationEmitInfo); } return { reportedDeclarationError: reportedDeclarationError, @@ -23185,13 +23487,12 @@ var ts; referencePathsOutput: referencePathsOutput }; function hasInternalAnnotation(range) { - var text = currentSourceFile.text; - var comment = text.substring(range.pos, range.end); + var comment = currentText.substring(range.pos, range.end); return comment.indexOf("@internal") >= 0; } function stripInternal(node) { if (node) { - var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + var leadingCommentRanges = ts.getLeadingCommentRanges(currentText, node.pos); if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) { return; } @@ -23272,7 +23573,7 @@ var ts; var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult); if (errorInfo) { if (errorInfo.typeName) { - diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); + diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); } else { diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); @@ -23336,9 +23637,9 @@ var ts; } function writeJsDocComments(declaration) { if (declaration) { - var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile); - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments); - ts.emitComments(currentSourceFile, writer, jsDocComments, true, newLine, ts.writeCommentRange); + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, true, newLine, ts.writeCommentRange); } } function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { @@ -23355,7 +23656,7 @@ var ts; case 103: case 97: case 9: - return writeTextOfNode(currentSourceFile, type); + return writeTextOfNode(currentText, type); case 188: return emitExpressionWithTypeArguments(type); case 151: @@ -23386,14 +23687,14 @@ var ts; } function writeEntityName(entityName) { if (entityName.kind === 69) { - writeTextOfNode(currentSourceFile, entityName); + writeTextOfNode(currentText, entityName); } else { var left = entityName.kind === 135 ? entityName.left : entityName.expression; var right = entityName.kind === 135 ? entityName.right : entityName.name; writeEntityName(left); write("."); - writeTextOfNode(currentSourceFile, right); + writeTextOfNode(currentText, right); } } function emitEntityName(entityName) { @@ -23421,7 +23722,7 @@ var ts; } } function emitTypePredicate(type) { - writeTextOfNode(currentSourceFile, type.parameterName); + writeTextOfNode(currentText, type.parameterName); write(" is "); emitType(type.type); } @@ -23461,20 +23762,23 @@ var ts; } } function emitSourceFile(node) { - currentSourceFile = node; + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); enclosingDeclaration = node; - ts.emitDetachedComments(currentSourceFile, writer, ts.writeCommentRange, node, newLine, true); + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true); emitLines(node.statements); } function getExportDefaultTempVariableName() { var baseName = "_default"; - if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) { + if (!ts.hasProperty(currentIdentifiers, baseName)) { return baseName; } var count = 0; while (true) { var name_18 = baseName + "_" + (++count); - if (!ts.hasProperty(currentSourceFile.identifiers, name_18)) { + if (!ts.hasProperty(currentIdentifiers, name_18)) { return name_18; } } @@ -23482,7 +23786,7 @@ var ts; function emitExportAssignment(node) { if (node.expression.kind === 69) { write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentSourceFile, node.expression); + writeTextOfNode(currentText, node.expression); } else { var tempVarName = getExportDefaultTempVariableName(); @@ -23517,7 +23821,7 @@ var ts; writeModuleElement(node); } else if (node.kind === 221 || - (node.parent.kind === 248 && ts.isExternalModule(currentSourceFile))) { + (node.parent.kind === 248 && isCurrentFileExternalModule)) { var isVisible; if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 248) { asynchronousSubModuleDeclarationEmitInfo.push({ @@ -23569,14 +23873,14 @@ var ts; } } function emitModuleElementDeclarationFlags(node) { - if (node.parent === currentSourceFile) { + if (node.parent.kind === 248) { if (node.flags & 2) { write("export "); } if (node.flags & 512) { write("default "); } - else if (node.kind !== 215) { + else if (node.kind !== 215 && !noDeclare) { write("declare "); } } @@ -23601,7 +23905,7 @@ var ts; write("export "); } write("import "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" = "); if (ts.isInternalModuleImportEqualsDeclaration(node)) { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); @@ -23609,7 +23913,7 @@ var ts; } else { write("require("); - writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node)); + writeTextOfNode(currentText, ts.getExternalModuleImportEqualsDeclarationExpression(node)); write(");"); } writer.writeLine(); @@ -23643,7 +23947,7 @@ var ts; if (node.importClause) { var currentWriterPos = writer.getTextPos(); if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentSourceFile, node.importClause.name); + writeTextOfNode(currentText, node.importClause.name); } if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { if (currentWriterPos !== writer.getTextPos()) { @@ -23651,7 +23955,7 @@ var ts; } if (node.importClause.namedBindings.kind === 224) { write("* as "); - writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name); + writeTextOfNode(currentText, node.importClause.namedBindings.name); } else { write("{ "); @@ -23661,16 +23965,28 @@ var ts; } write(" from "); } - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); write(";"); writer.writeLine(); } + function emitExternalModuleSpecifier(moduleSpecifier) { + if (moduleSpecifier.kind === 9 && (!root) && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, moduleSpecifier.parent); + if (moduleName) { + write("\""); + write(moduleName); + write("\""); + return; + } + } + writeTextOfNode(currentText, moduleSpecifier); + } function emitImportOrExportSpecifier(node) { if (node.propertyName) { - writeTextOfNode(currentSourceFile, node.propertyName); + writeTextOfNode(currentText, node.propertyName); write(" as "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } function emitExportSpecifier(node) { emitImportOrExportSpecifier(node); @@ -23690,7 +24006,7 @@ var ts; } if (node.moduleSpecifier) { write(" from "); - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); } write(";"); writer.writeLine(); @@ -23704,11 +24020,11 @@ var ts; else { write("module "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); while (node.body.kind !== 219) { node = node.body; write("."); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; @@ -23727,7 +24043,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); @@ -23749,7 +24065,7 @@ var ts; write("const "); } write("enum "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" {"); writeLine(); increaseIndent(); @@ -23760,7 +24076,7 @@ var ts; } function emitEnumMemberDeclaration(node) { emitJsDocComments(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var enumMemberValue = resolver.getConstantValue(node); if (enumMemberValue !== undefined) { write(" = "); @@ -23777,7 +24093,7 @@ var ts; increaseIndent(); emitJsDocComments(node); decreaseIndent(); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (node.constraint && !isPrivateMethodTypeParameter(node)) { write(" extends "); if (node.parent.kind === 152 || @@ -23887,7 +24203,7 @@ var ts; write("abstract "); } write("class "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -23910,7 +24226,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("interface "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -23940,7 +24256,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if ((node.kind === 141 || node.kind === 140) && ts.hasQuestionToken(node)) { write("?"); } @@ -24014,7 +24330,7 @@ var ts; emitBindingPattern(bindingElement.name); } else { - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); writeTypeOfDeclaration(bindingElement, undefined, getBindingElementTypeVisibilityError); } } @@ -24055,7 +24371,7 @@ var ts; emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.setAccessor); emitClassMemberDeclarationFlags(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (!(node.flags & 16)) { accessorWithTypeAnnotation = node; var type = getTypeAnnotationFromAccessor(node); @@ -24136,13 +24452,13 @@ var ts; } if (node.kind === 213) { write("function "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } else if (node.kind === 144) { write("constructor"); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (ts.hasQuestionToken(node)) { write("?"); } @@ -24255,7 +24571,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } if (resolver.isOptionalParameter(node)) { write("?"); @@ -24354,7 +24670,7 @@ var ts; } else if (bindingElement.kind === 163) { if (bindingElement.propertyName) { - writeTextOfNode(currentSourceFile, bindingElement.propertyName); + writeTextOfNode(currentText, bindingElement.propertyName); write(": "); } if (bindingElement.name) { @@ -24366,7 +24682,7 @@ var ts; if (bindingElement.dotDotDotToken) { write("..."); } - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); } } } @@ -24449,6 +24765,18 @@ var ts; return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile); } ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || ts.isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; var entities = { "quot": 0x0022, "amp": 0x0026, @@ -24718,15 +25046,19 @@ var ts; var newLine = host.getNewLine(); var jsxDesugaring = host.getCompilerOptions().jsx !== 1; var shouldEmitJsx = function (s) { return (s.languageVariant === 1 && !jsxDesugaring); }; + var outFile = compilerOptions.outFile || compilerOptions.out; + var emitJavaScript = createFileEmitter(); if (targetSourceFile === undefined) { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { - var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); - emitFile(jsFilePath, sourceFile); - } - }); - if (compilerOptions.outFile || compilerOptions.out) { - emitFile(compilerOptions.outFile || compilerOptions.out); + if (outFile) { + emitFile(outFile); + } + else { + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { + var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); + emitFile(jsFilePath, sourceFile); + } + }); } } else { @@ -24734,8 +25066,8 @@ var ts; var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js"); emitFile(jsFilePath, targetSourceFile); } - else if (!ts.isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) { - emitFile(compilerOptions.outFile || compilerOptions.out); + else if (!ts.isDeclarationFile(targetSourceFile) && outFile) { + emitFile(outFile); } } diagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics); @@ -24785,20 +25117,26 @@ var ts; } } } - function emitJavaScript(jsFilePath, root) { + function createFileEmitter() { var writer = ts.createTextWriter(newLine); var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; var currentSourceFile; + var currentText; + var currentLineMap; + var currentFileIdentifiers; + var renamedDependencies; + var isEs6Module; + var isCurrentFileExternalModule; var exportFunctionForFile; - var generatedNameSet = {}; - var nodeToGeneratedName = []; + var generatedNameSet; + var nodeToGeneratedName; var computedPropertyNamesToGeneratedNames; var convertedLoopState; - var extendsEmitted = false; - var decorateEmitted = false; - var paramEmitted = false; - var awaiterEmitted = false; - var tempFlags = 0; + var extendsEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var tempFlags; var tempVariables; var tempParameters; var externalImports; @@ -24815,6 +25153,7 @@ var ts; var scopeEmitStart = function (scopeDeclaration, scopeName) { }; var scopeEmitEnd = function () { }; var sourceMapData; + var root; var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; var moduleEmitDelegates = (_a = {}, _a[5] = emitES6Module, @@ -24824,30 +25163,75 @@ var ts; _a[1] = emitCommonJSModule, _a ); - if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { - initializeEmitterWithSourceMaps(); - } - if (root) { - emitSourceFile(root); - } - else { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - emitSourceFile(sourceFile); + var bundleEmitDelegates = (_b = {}, + _b[5] = function () { }, + _b[2] = emitAMDModule, + _b[4] = emitSystemModule, + _b[3] = function () { }, + _b[1] = function () { }, + _b + ); + return doEmit; + function doEmit(jsFilePath, rootFile) { + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = {}; + nodeToGeneratedName = []; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = rootFile; + if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { + initializeEmitterWithSourceMaps(jsFilePath, root); + } + if (root) { + emitSourceFile(root); + } + else { + if (modulekind) { + ts.forEach(host.getSourceFiles(), emitEmitHelpers); } - }); + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if ((!isExternalModuleOrDeclarationFile(sourceFile)) || (modulekind && ts.isExternalModule(sourceFile))) { + emitSourceFile(sourceFile); + } + }); + } + writeLine(); + writeEmittedFiles(writer.getText(), jsFilePath, compilerOptions.emitBOM); } - writeLine(); - writeEmittedFiles(writer.getText(), compilerOptions.emitBOM); - return; function emitSourceFile(sourceFile) { currentSourceFile = sourceFile; + currentText = sourceFile.text; + currentLineMap = ts.getLineStarts(sourceFile); exportFunctionForFile = undefined; + isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; + renamedDependencies = sourceFile.renamedDependencies; + currentFileIdentifiers = sourceFile.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(sourceFile); emit(sourceFile); } function isUniqueName(name) { return !resolver.hasGlobalName(name) && - !ts.hasProperty(currentSourceFile.identifiers, name) && + !ts.hasProperty(currentFileIdentifiers, name) && !ts.hasProperty(generatedNameSet, name); } function makeTempVariableName(flags) { @@ -24920,7 +25304,7 @@ var ts; var id = ts.getNodeId(node); return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); } - function initializeEmitterWithSourceMaps() { + function initializeEmitterWithSourceMaps(jsFilePath, root) { var sourceMapDir; var sourceMapSourceIndex = -1; var sourceMapNameIndexMap = {}; @@ -24989,7 +25373,7 @@ var ts; } } function recordSourceMapSpan(pos) { - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + var sourceLinePos = ts.computeLineAndCharacterOfPosition(currentLineMap, pos); sourceLinePos.line++; sourceLinePos.character++; var emittedLine = writer.getLine(); @@ -25017,13 +25401,13 @@ var ts; } } function recordEmitNodeStartSpan(node) { - recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos)); + recordSourceMapSpan(ts.skipTrivia(currentText, node.pos)); } function recordEmitNodeEndSpan(node) { recordSourceMapSpan(node.end); } function writeTextWithSpanRecord(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos); + var tokenStartPos = ts.skipTrivia(currentText, startPos); recordSourceMapSpan(tokenStartPos); var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn); recordSourceMapSpan(tokenEndPos); @@ -25093,9 +25477,9 @@ var ts; sourceMapNameIndices.pop(); } ; - function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) { + function writeCommentRangeWithMap(currentText, currentLineMap, writer, comment, newLine) { recordSourceMapSpan(comment.pos); - ts.writeCommentRange(currentSourceFile, writer, comment, newLine); + ts.writeCommentRange(currentText, currentLineMap, writer, comment, newLine); recordSourceMapSpan(comment.end); } function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings, sourcesContent) { @@ -25125,7 +25509,7 @@ var ts; return output; } } - function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptAndSourceMapFile(emitOutput, jsFilePath, writeByteOrderMark) { encodeLastRecordedSourceMapSpan(); var sourceMapText = serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings, sourceMapData.sourceMapSourcesContent); sourceMapDataList.push(sourceMapData); @@ -25138,7 +25522,7 @@ var ts; ts.writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, sourceMapText, false); sourceMapUrl = "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL; } - writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark); + writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark); } var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath)); sourceMapData = { @@ -25201,7 +25585,7 @@ var ts; scopeEmitEnd = recordScopeNameEnd; writeComment = writeCommentRangeWithMap; } - function writeJavaScriptFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptFile(emitOutput, jsFilePath, writeByteOrderMark) { ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark); } function createTempVariable(flags) { @@ -25371,7 +25755,7 @@ var ts; return getQuotedEscapedLiteralText("\"", node.text, "\""); } if (node.parent) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + return ts.getTextOfNodeFromSourceText(currentText, node); } switch (node.kind) { case 9: @@ -25393,7 +25777,7 @@ var ts; return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote; } function emitDownlevelRawTemplateLiteral(node) { - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + var text = ts.getTextOfNodeFromSourceText(currentText, node); var isLast = node.kind === 11 || node.kind === 14; text = text.substring(1, text.length - (isLast ? 1 : 2)); text = text.replace(/\r\n?/g, "\n"); @@ -25723,7 +26107,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } write("\""); } @@ -25819,7 +26203,7 @@ var ts; else if (declaration.kind === 226) { write(getGeneratedNameForNode(declaration.parent.parent.parent)); var name_23 = declaration.propertyName || declaration.name; - var identifier = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, name_23); + var identifier = ts.getTextOfNodeFromSourceText(currentText, name_23); if (languageVersion === 0 && identifier === "default") { write("[\"default\"]"); } @@ -25843,7 +26227,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function isNameOfNestedRedeclaration(node) { @@ -25880,7 +26264,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function emitThis(node) { @@ -26247,8 +26631,8 @@ var ts; return container && container.kind !== 248; } function emitShorthandPropertyAssignment(node) { - writeTextOfNode(currentSourceFile, node.name); - if (languageVersion < 2 || isNamespaceExportReference(node.name)) { + writeTextOfNode(currentText, node.name); + if (modulekind !== 5 || isNamespaceExportReference(node.name)) { write(": "); emit(node.name); } @@ -26298,10 +26682,10 @@ var ts; } emit(node.expression); var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); - var shouldEmitSpace; + var shouldEmitSpace = false; if (!indentedBeforeDot) { if (node.expression.kind === 8) { - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression); + var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); shouldEmitSpace = text.indexOf(ts.tokenToString(21)) < 0; } else { @@ -27307,16 +27691,16 @@ var ts; emitToken(16, node.clauses.end); } function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, node2.end); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); } function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function emitCaseOrDefaultClause(node) { if (node.kind === 241) { @@ -27421,7 +27805,7 @@ var ts; if (node.parent.kind === 248) { ts.Debug.assert(!!(node.flags & 512) || node.kind === 227); if (modulekind === 1 || modulekind === 2 || modulekind === 3) { - if (!currentSourceFile.symbol.exports["___esModule"]) { + if (!isEs6Module) { if (languageVersion === 1) { write("Object.defineProperty(exports, \"__esModule\", { value: true });"); writeLine(); @@ -27584,12 +27968,18 @@ var ts; return node; } function createPropertyAccessForDestructuringProperty(object, propName) { - var syntheticName = ts.createSynthesizedNode(propName.kind); - syntheticName.text = propName.text; - if (syntheticName.kind !== 69) { - return createElementAccessExpression(object, syntheticName); + var index; + var nameIsComputed = propName.kind === 136; + if (nameIsComputed) { + index = ensureIdentifier(propName.expression, false); } - return createPropertyAccessExpression(object, syntheticName); + else { + index = ts.createSynthesizedNode(propName.kind); + index.text = propName.text; + } + return !nameIsComputed && index.kind === 69 + ? createPropertyAccessExpression(object, index) + : createElementAccessExpression(object, index); } function createSliceCall(value, sliceIndex) { var call = ts.createSynthesizedNode(168); @@ -28003,7 +28393,6 @@ var ts; var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); var isArrowFunction = node.kind === 174; var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 4096) !== 0; - var args; if (!isArrowFunction) { write(" {"); increaseIndent(); @@ -29177,8 +29566,8 @@ var ts; } } function tryRenameExternalModule(moduleName) { - if (currentSourceFile.renamedDependencies && ts.hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) { - return "\"" + currentSourceFile.renamedDependencies[moduleName.text] + "\""; + if (renamedDependencies && ts.hasProperty(renamedDependencies, moduleName.text)) { + return "\"" + renamedDependencies[moduleName.text] + "\""; } return undefined; } @@ -29318,7 +29707,7 @@ var ts; return; } if (resolver.isReferencedAliasDeclaration(node) || - (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { + (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { emitLeadingComments(node); emitStart(node); var variableDeclarationIsHoisted = shouldHoistVariable(node, true); @@ -29530,7 +29919,7 @@ var ts; function getLocalNameForExternalImport(node) { var namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); + return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); } if (node.kind === 222 && node.importClause) { return getGeneratedNameForNode(node); @@ -29803,7 +30192,7 @@ var ts; ts.getEnclosingBlockScopeContainer(node).kind === 248; } function isCurrentFileSystemExternalModule() { - return modulekind === 4 && ts.isExternalModule(currentSourceFile); + return modulekind === 4 && isCurrentFileExternalModule; } function emitSystemModuleBody(node, dependencyGroups, startIndex) { emitVariableDeclarationsForImports(); @@ -29916,15 +30305,19 @@ var ts; writeLine(); write("}"); } - function emitSystemModule(node) { + function writeModuleName(node, emitRelativePathAsModuleName) { + var moduleName = node.moduleName; + if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { + write("\"" + moduleName + "\", "); + } + } + function emitSystemModule(node, emitRelativePathAsModuleName) { collectExternalModuleInfo(node); ts.Debug.assert(!exportFunctionForFile); exportFunctionForFile = makeUniqueName("exports"); writeLine(); write("System.register("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } + writeModuleName(node, emitRelativePathAsModuleName); write("["); var groupIndices = {}; var dependencyGroups = []; @@ -29942,6 +30335,12 @@ var ts; if (i !== 0) { write(", "); } + if (emitRelativePathAsModuleName) { + var name_29 = getExternalModuleNameFromDeclaration(host, resolver, externalImports[i]); + if (name_29) { + text = "\"" + name_29 + "\""; + } + } write(text); } write("], function(" + exportFunctionForFile + ") {"); @@ -29955,7 +30354,7 @@ var ts; writeLine(); write("});"); } - function getAMDDependencyNames(node, includeNonAmdDependencies) { + function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { var aliasedModuleNames = []; var unaliasedModuleNames = []; var importAliasNames = []; @@ -29972,6 +30371,12 @@ var ts; for (var _c = 0, externalImports_4 = externalImports; _c < externalImports_4.length; _c++) { var importNode = externalImports_4[_c]; var externalModuleName = getExternalModuleNameText(importNode); + if (emitRelativePathAsModuleName) { + var name_30 = getExternalModuleNameFromDeclaration(host, resolver, importNode); + if (name_30) { + externalModuleName = "\"" + name_30 + "\""; + } + } var importAliasName = getLocalNameForExternalImport(importNode); if (includeNonAmdDependencies && importAliasName) { aliasedModuleNames.push(externalModuleName); @@ -29983,8 +30388,8 @@ var ts; } return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies) { - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies); + function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { + var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); emitAMDDependencyList(dependencyNames); write(", "); emitAMDFactoryHeader(dependencyNames); @@ -30011,15 +30416,13 @@ var ts; } write(") {"); } - function emitAMDModule(node) { + function emitAMDModule(node, emitRelativePathAsModuleName) { emitEmitHelpers(node); collectExternalModuleInfo(node); writeLine(); write("define("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } - emitAMDDependencies(node, true); + writeModuleName(node, emitRelativePathAsModuleName); + emitAMDDependencies(node, true, emitRelativePathAsModuleName); increaseIndent(); var startIndex = emitDirectivePrologues(node.statements, true); emitExportStarHelper(); @@ -30225,8 +30628,13 @@ var ts; emitShebang(); emitDetachedCommentsAndUpdateCommentsInfo(node); if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1]; - emitModule(node); + if (root || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { + var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1]; + emitModule(node); + } + else { + bundleEmitDelegates[modulekind](node, true); + } } else { var startIndex = emitDirectivePrologues(node.statements, false); @@ -30470,7 +30878,7 @@ var ts; return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; } function getLeadingCommentsWithoutDetachedComments() { - var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); + var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); } @@ -30480,10 +30888,10 @@ var ts; return leadingComments; } function isTripleSlashComment(comment) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 && + if (currentText.charCodeAt(comment.pos + 1) === 47 && comment.pos + 2 < comment.end && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 47) { - var textSubStr = currentSourceFile.text.substring(comment.pos, comment.end); + currentText.charCodeAt(comment.pos + 2) === 47) { + var textSubStr = currentText.substring(comment.pos, comment.end); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? true : false; @@ -30497,7 +30905,7 @@ var ts; return getLeadingCommentsWithoutDetachedComments(); } else { - return ts.getLeadingCommentRangesOfNode(node, currentSourceFile); + return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); } } } @@ -30505,7 +30913,7 @@ var ts; function getTrailingCommentsToEmit(node) { if (node.parent) { if (node.parent.kind === 248 || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentSourceFile.text, node.end); + return ts.getTrailingCommentRanges(currentText, node.end); } } } @@ -30528,22 +30936,22 @@ var ts; leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); } } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, true, newLine, writeComment); } function emitTrailingComments(node) { if (compilerOptions.removeComments) { return; } var trailingComments = getTrailingCommentsToEmit(node); - ts.emitComments(currentSourceFile, writer, trailingComments, false, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, false, newLine, writeComment); } function emitTrailingCommentsOfPosition(pos) { if (compilerOptions.removeComments) { return; } - var trailingComments = ts.getTrailingCommentRanges(currentSourceFile.text, pos); - ts.emitComments(currentSourceFile, writer, trailingComments, true, newLine, writeComment); + var trailingComments = ts.getTrailingCommentRanges(currentText, pos); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, true, newLine, writeComment); } function emitLeadingCommentsOfPositionWorker(pos) { if (compilerOptions.removeComments) { @@ -30554,13 +30962,13 @@ var ts; leadingComments = getLeadingCommentsWithoutDetachedComments(); } else { - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos); + leadingComments = ts.getLeadingCommentRanges(currentText, pos); } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments); - ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, true, newLine, writeComment); } function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments); + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -30571,12 +30979,12 @@ var ts; } } function emitShebang() { - var shebang = ts.getShebang(currentSourceFile.text); + var shebang = ts.getShebang(currentText); if (shebang) { write(shebang); } } - var _a; + var _a, _b; } function emitFile(jsFilePath, sourceFile) { emitJavaScript(jsFilePath, sourceFile); @@ -30632,11 +31040,11 @@ var ts; if (ts.getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { var failedLookupLocations = []; var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var resolvedFileName = loadNodeModuleFromFile(ts.supportedJsExtensions, candidate, failedLookupLocations, host); if (resolvedFileName) { return { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations }; } - resolvedFileName = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + resolvedFileName = loadNodeModuleFromDirectory(ts.supportedJsExtensions, candidate, failedLookupLocations, host); return resolvedFileName ? { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations } : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; @@ -30646,8 +31054,8 @@ var ts; } } ts.nodeModuleNameResolver = nodeModuleNameResolver; - function loadNodeModuleFromFile(candidate, failedLookupLocation, host) { - return ts.forEach(ts.moduleFileExtensions, tryLoad); + function loadNodeModuleFromFile(extensions, candidate, failedLookupLocation, host) { + return ts.forEach(extensions, tryLoad); function tryLoad(ext) { var fileName = ts.fileExtensionIs(candidate, ext) ? candidate : candidate + ext; if (host.fileExists(fileName)) { @@ -30659,7 +31067,7 @@ var ts; } } } - function loadNodeModuleFromDirectory(candidate, failedLookupLocation, host) { + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, host) { var packageJsonPath = ts.combinePaths(candidate, "package.json"); if (host.fileExists(packageJsonPath)) { var jsonContent; @@ -30671,7 +31079,7 @@ var ts; jsonContent = { typings: undefined }; } if (jsonContent.typings) { - var result = loadNodeModuleFromFile(ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); + var result = loadNodeModuleFromFile(extensions, ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); if (result) { return result; } @@ -30680,7 +31088,7 @@ var ts; else { failedLookupLocation.push(packageJsonPath); } - return loadNodeModuleFromFile(ts.combinePaths(candidate, "index"), failedLookupLocation, host); + return loadNodeModuleFromFile(extensions, ts.combinePaths(candidate, "index"), failedLookupLocation, host); } function loadModuleFromNodeModules(moduleName, directory, host) { var failedLookupLocations = []; @@ -30690,11 +31098,11 @@ var ts; if (baseName !== "node_modules") { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var result = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var result = loadNodeModuleFromFile(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } - result = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + result = loadNodeModuleFromDirectory(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } @@ -30719,9 +31127,10 @@ var ts; var searchName; var failedLookupLocations = []; var referencedSourceFile; + var extensions = compilerOptions.allowNonTsExtensions ? ts.supportedJsExtensions : ts.supportedExtensions; while (true) { searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleName)); - referencedSourceFile = ts.forEach(ts.supportedExtensions, function (extension) { + referencedSourceFile = ts.forEach(extensions, function (extension) { if (extension === ".tsx" && !compilerOptions.jsx) { return undefined; } @@ -30749,10 +31158,8 @@ var ts; ts.classicNameResolver = classicNameResolver; ts.defaultInitCompilerOptions = { module: 1, - target: 0, + target: 1, noImplicitAny: false, - outDir: "built", - rootDir: ".", sourceMap: false }; function createCompilerHost(options, setParentNodes) { @@ -31110,35 +31517,47 @@ var ts; if (file.imports) { return; } + var isJavaScriptFile = ts.isSourceFileJavaScript(file); var imports; for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collect(node, true); + collect(node, true, false); } file.imports = imports || emptyArray; - function collect(node, allowRelativeModuleNames) { - switch (node.kind) { - case 222: - case 221: - case 228: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9) { + return; + function collect(node, allowRelativeModuleNames, collectOnlyRequireCalls) { + if (!collectOnlyRequireCalls) { + switch (node.kind) { + case 222: + case 221: + case 228: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9) { + break; + } + if (!moduleNameExpr.text) { + break; + } + if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); + } break; - } - if (!moduleNameExpr.text) { + case 218: + if (node.name.kind === 9 && (node.flags & 4 || ts.isDeclarationFile(file))) { + ts.forEachChild(node.body, function (node) { + collect(node, false, collectOnlyRequireCalls); + }); + } break; - } - if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 218: - if (node.name.kind === 9 && (node.flags & 4 || ts.isDeclarationFile(file))) { - ts.forEachChild(node.body, function (node) { - collect(node, false); - }); - } - break; + } + } + if (isJavaScriptFile) { + if (ts.isRequireCall(node)) { + (imports || (imports = [])).push(node.arguments[0]); + } + else { + ts.forEachChild(node, function (node) { return collect(node, allowRelativeModuleNames, true); }); + } } } } @@ -31225,7 +31644,6 @@ var ts; } processImportedModules(file, basePath); if (isDefaultLib) { - file.isDefaultLib = true; files.unshift(file); } else { @@ -31298,6 +31716,9 @@ var ts; commonPathComponents.length = sourcePathComponents.length; } }); + if (!commonPathComponents) { + return currentDirectory; + } return ts.getNormalizedPathFromPathComponents(commonPathComponents); } function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { @@ -31380,10 +31801,12 @@ var ts; if (options.module === 5 && languageVersion < 2) { programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower)); } + if (outFile && options.module && !(options.module === 2 || options.module === 4)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } if (options.outDir || options.sourceRoot || - (options.mapRoot && - (!outFile || firstExternalModuleSourceFile !== undefined))) { + options.mapRoot) { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); } @@ -31862,20 +32285,20 @@ var ts; var exclude = json["exclude"] instanceof Array ? ts.map(json["exclude"], ts.normalizeSlashes) : undefined; var sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); for (var i = 0; i < sysFiles.length; i++) { - var name_29 = sysFiles[i]; - if (ts.fileExtensionIs(name_29, ".d.ts")) { - var baseName = name_29.substr(0, name_29.length - ".d.ts".length); + var name_31 = sysFiles[i]; + if (ts.fileExtensionIs(name_31, ".d.ts")) { + var baseName = name_31.substr(0, name_31.length - ".d.ts".length); if (!ts.contains(sysFiles, baseName + ".tsx") && !ts.contains(sysFiles, baseName + ".ts")) { - fileNames.push(name_29); + fileNames.push(name_31); } } - else if (ts.fileExtensionIs(name_29, ".ts")) { - if (!ts.contains(sysFiles, name_29 + "x")) { - fileNames.push(name_29); + else if (ts.fileExtensionIs(name_31, ".ts")) { + if (!ts.contains(sysFiles, name_31 + "x")) { + fileNames.push(name_31); } } else { - fileNames.push(name_29); + fileNames.push(name_31); } } } @@ -31994,14 +32417,15 @@ var ts; var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); return diagnostic.messageText; } + function getRelativeFileName(fileName, host) { + return host ? ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : fileName; + } function reportDiagnosticSimply(diagnostic, host) { var output = ""; if (diagnostic.file) { var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; - var relativeFileName = host - ? ts.convertToRelativePath(diagnostic.file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) - : diagnostic.file.fileName; - output += diagnostic.file.fileName + "(" + (line + 1) + "," + (character + 1) + "): "; + var relativeFileName = getRelativeFileName(diagnostic.file.fileName, host); + output += relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): "; } var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); output += category + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine; @@ -32030,6 +32454,7 @@ var ts; var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; var _b = ts.getLineAndCharacterOfPosition(file, start + length_3), lastLine = _b.line, lastLineChar = _b.character; var lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; + var relativeFileName = getRelativeFileName(file.fileName, host); var hasMoreThanFiveLines = (lastLine - firstLine) >= 4; var gutterWidth = (lastLine + 1 + "").length; if (hasMoreThanFiveLines) { @@ -32065,7 +32490,7 @@ var ts; output += ts.sys.newLine; } output += ts.sys.newLine; - output += file.fileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; + output += relativeFileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; } var categoryColor = categoryFormatMap[diagnostic.category]; var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); @@ -32191,8 +32616,19 @@ var ts; return; } } + if (!cachedConfigFileText) { + var error = ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, configFileName); + reportDiagnostics([error], undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } var result = ts.parseConfigFileTextToJson(configFileName, cachedConfigFileText); var configObject = result.config; + if (!configObject) { + reportDiagnostics([result.error], undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } var configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, ts.getDirectoryPath(configFileName)); if (configParseResult.errors.length > 0) { reportDiagnostics(configParseResult.errors, undefined); @@ -32455,10 +32891,10 @@ var ts; function serializeCompilerOptions(options) { var result = {}; var optionsNameMap = ts.getOptionNameMap().optionNameMap; - for (var name_30 in options) { - if (ts.hasProperty(options, name_30)) { - var value = options[name_30]; - switch (name_30) { + for (var name_32 in options) { + if (ts.hasProperty(options, name_32)) { + var value = options[name_32]; + switch (name_32) { case "init": case "watch": case "version": @@ -32466,17 +32902,17 @@ var ts; case "project": break; default: - var optionDefinition = optionsNameMap[name_30.toLowerCase()]; + var optionDefinition = optionsNameMap[name_32.toLowerCase()]; if (optionDefinition) { if (typeof optionDefinition.type === "string") { - result[name_30] = value; + result[name_32] = value; } else { var typeMap = optionDefinition.type; for (var key in typeMap) { if (ts.hasProperty(typeMap, key)) { if (typeMap[key] === value) - result[name_30] = key; + result[name_32] = key; } } } diff --git a/lib/tsserver.js b/lib/tsserver.js index 2893dab82ef..9f0c1674080 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -665,7 +665,7 @@ var ts; } ts.fileExtensionIs = fileExtensionIs; ts.supportedExtensions = [".ts", ".tsx", ".d.ts"]; - ts.moduleFileExtensions = ts.supportedExtensions; + ts.supportedJsExtensions = ts.supportedExtensions.concat(".js", ".jsx"); function isSupportedSourceFileName(fileName) { if (!fileName) { return false; @@ -716,17 +716,16 @@ var ts; } function Signature(checker) { } + function Node(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0; + this.parent = undefined; + } ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0; - this.parent = undefined; - } - Node.prototype = { kind: kind }; - return Node; - }, + getNodeConstructor: function () { return Node; }, + getSourceFileConstructor: function () { return Node; }, getSymbolConstructor: function () { return Symbol; }, getTypeConstructor: function () { return Type; }, getSignatureConstructor: function () { return Signature; } @@ -1003,7 +1002,16 @@ var ts; if (writeByteOrderMark) { data = "\uFEFF" + data; } - _fs.writeFileSync(fileName, data, "utf8"); + var fd; + try { + fd = _fs.openSync(fileName, "w"); + _fs.writeSync(fd, data, undefined, "utf8"); + } + finally { + if (fd !== undefined) { + _fs.closeSync(fd); + } + } } function getCanonicalPath(path) { return useCaseSensitiveFileNames ? path.toLowerCase() : path; @@ -1688,6 +1696,7 @@ var ts; Disallow_inconsistently_cased_references_to_the_same_file: { code: 6078, category: ts.DiagnosticCategory.Message, key: "Disallow_inconsistently_cased_references_to_the_same_file_6078", message: "Disallow inconsistently-cased references to the same file." }, Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: ts.DiagnosticCategory.Message, key: "Specify_JSX_code_generation_Colon_preserve_or_react_6080", message: "Specify JSX code generation: 'preserve' or 'react'" }, Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: ts.DiagnosticCategory.Message, key: "Argument_for_jsx_must_be_preserve_or_react_6081", message: "Argument for '--jsx' must be 'preserve' or 'react'." }, + Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -2148,7 +2157,7 @@ var ts; function getCommentRanges(text, pos, trailing) { var result; var collecting = trailing || pos === 0; - while (true) { + while (pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13: @@ -2217,6 +2226,7 @@ var ts; } return result; } + return result; } function getLeadingCommentRanges(text, pos) { return getCommentRanges(text, pos, false); @@ -2312,7 +2322,7 @@ var ts; error(ts.Diagnostics.Digit_expected); } } - return +(text.substring(start, end)); + return "" + +(text.substring(start, end)); } function scanOctalDigits() { var start = pos; @@ -2704,7 +2714,7 @@ var ts; return pos++, token = 36; case 46: if (isDigit(text.charCodeAt(pos + 1))) { - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8; } if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) { @@ -2801,7 +2811,7 @@ var ts; case 55: case 56: case 57: - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8; case 58: return pos++, token = 54; @@ -3879,6 +3889,10 @@ var ts; return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + function isExternalOrCommonJsModule(file) { + return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; + } + ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isDeclarationFile(file) { return (file.flags & 4096) !== 0; } @@ -3925,18 +3939,26 @@ var ts; return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; + function getLeadingCommentRangesOfNodeFromText(node, text) { + return ts.getLeadingCommentRanges(text, node.pos); + } + ts.getLeadingCommentRangesOfNodeFromText = getLeadingCommentRangesOfNodeFromText; function getJsDocComments(node, sourceFileOfNode) { - var commentRanges = (node.kind === 138 || node.kind === 137) ? - ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : - getLeadingCommentRangesOfNode(node, sourceFileOfNode); - return ts.filter(commentRanges, isJsDocComment); - function isJsDocComment(comment) { - return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 && - sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 && - sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47; - } + return getJsDocCommentsFromText(node, sourceFileOfNode.text); } ts.getJsDocComments = getJsDocComments; + function getJsDocCommentsFromText(node, text) { + var commentRanges = (node.kind === 138 || node.kind === 137) ? + ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : + getLeadingCommentRangesOfNodeFromText(node, text); + return ts.filter(commentRanges, isJsDocComment); + function isJsDocComment(comment) { + return text.charCodeAt(comment.pos + 1) === 42 && + text.charCodeAt(comment.pos + 2) === 42 && + text.charCodeAt(comment.pos + 3) !== 47; + } + } + ts.getJsDocCommentsFromText = getJsDocCommentsFromText; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; function isTypeNode(node) { @@ -4465,6 +4487,41 @@ var ts; return node.kind === 221 && node.moduleReference.kind !== 232; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; + function isSourceFileJavaScript(file) { + return isInJavaScriptFile(file); + } + ts.isSourceFileJavaScript = isSourceFileJavaScript; + function isInJavaScriptFile(node) { + return node && !!(node.parserContextFlags & 32); + } + ts.isInJavaScriptFile = isInJavaScriptFile; + function isRequireCall(expression) { + return expression.kind === 168 && + expression.expression.kind === 69 && + expression.expression.text === "require" && + expression.arguments.length === 1 && + expression.arguments[0].kind === 9; + } + ts.isRequireCall = isRequireCall; + function isExportsPropertyAssignment(expression) { + return isInJavaScriptFile(expression) && + (expression.kind === 181) && + (expression.operatorToken.kind === 56) && + (expression.left.kind === 166) && + (expression.left.expression.kind === 69) && + ((expression.left.expression).text === "exports"); + } + ts.isExportsPropertyAssignment = isExportsPropertyAssignment; + function isModuleExportsAssignment(expression) { + return isInJavaScriptFile(expression) && + (expression.kind === 181) && + (expression.operatorToken.kind === 56) && + (expression.left.kind === 166) && + (expression.left.expression.kind === 69) && + ((expression.left.expression).text === "module") && + (expression.left.name.text === "exports"); + } + ts.isModuleExportsAssignment = isModuleExportsAssignment; function getExternalModuleName(node) { if (node.kind === 222) { return node.moduleSpecifier; @@ -4776,8 +4833,8 @@ var ts; function getFileReferenceFromReferencePath(comment, commentRange) { var simpleReferenceRegEx = /^\/\/\/\s*/gim; - if (simpleReferenceRegEx.exec(comment)) { - if (isNoDefaultLibRegEx.exec(comment)) { + if (simpleReferenceRegEx.test(comment)) { + if (isNoDefaultLibRegEx.test(comment)) { return { isNoDefaultLib: true }; @@ -4819,12 +4876,20 @@ var ts; return isFunctionLike(node) && (node.flags & 256) !== 0 && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; + function isStringOrNumericLiteral(kind) { + return kind === 9 || kind === 8; + } + ts.isStringOrNumericLiteral = isStringOrNumericLiteral; function hasDynamicName(declaration) { - return declaration.name && - declaration.name.kind === 136 && - !isWellKnownSymbolSyntactically(declaration.name.expression); + return declaration.name && isDynamicName(declaration.name); } ts.hasDynamicName = hasDynamicName; + function isDynamicName(name) { + return name.kind === 136 && + !isStringOrNumericLiteral(name.expression.kind) && + !isWellKnownSymbolSyntactically(name.expression); + } + ts.isDynamicName = isDynamicName; function isWellKnownSymbolSyntactically(node) { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } @@ -5045,11 +5110,11 @@ var ts; } ts.getIndentSize = getIndentSize; function createTextWriter(newLine) { - var output = ""; - var indent = 0; - var lineStart = true; - var lineCount = 0; - var linePos = 0; + var output; + var indent; + var lineStart; + var lineCount; + var linePos; function write(s) { if (s && s.length) { if (lineStart) { @@ -5059,6 +5124,13 @@ var ts; output += s; } } + function reset() { + output = ""; + indent = 0; + lineStart = true; + lineCount = 0; + linePos = 0; + } function rawWrite(s) { if (s !== undefined) { if (lineStart) { @@ -5085,9 +5157,10 @@ var ts; lineStart = true; } } - function writeTextOfNode(sourceFile, node) { - write(getSourceTextOfNodeFromSourceFile(sourceFile, node)); + function writeTextOfNode(text, node) { + write(getTextOfNodeFromSourceText(text, node)); } + reset(); return { write: write, rawWrite: rawWrite, @@ -5100,10 +5173,17 @@ var ts; getTextPos: function () { return output.length; }, getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, - getText: function () { return output; } + getText: function () { return output; }, + reset: reset }; } ts.createTextWriter = createTextWriter; + function getExternalModuleNameFromPath(host, fileName) { + var dir = host.getCurrentDirectory(); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, fileName, dir, function (f) { return host.getCanonicalFileName(f); }, false); + return ts.removeFileExtension(relativePath); + } + ts.getExternalModuleNameFromPath = getExternalModuleNameFromPath; function getOwnEmitOutputFilePath(sourceFile, host, extension) { var compilerOptions = host.getCompilerOptions(); var emitOutputFilePathWithoutExtension; @@ -5132,6 +5212,10 @@ var ts; return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line; } ts.getLineOfLocalPosition = getLineOfLocalPosition; + function getLineOfLocalPositionFromLineMap(lineMap, pos) { + return ts.computeLineAndCharacterOfPosition(lineMap, pos).line; + } + ts.getLineOfLocalPositionFromLineMap = getLineOfLocalPositionFromLineMap; function getFirstConstructorWithBody(node) { return ts.forEach(node.members, function (member) { if (member.kind === 144 && nodeIsPresent(member.body)) { @@ -5202,21 +5286,21 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; - function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) { + function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) { + getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) { + function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { var emitLeadingSpace = !trailingSeparator; ts.forEach(comments, function (comment) { if (emitLeadingSpace) { writer.write(" "); emitLeadingSpace = false; } - writeComment(currentSourceFile, writer, comment, newLine); + writeComment(text, lineMap, writer, comment, newLine); if (comment.hasTrailingNewLine) { writer.writeLine(); } @@ -5229,16 +5313,16 @@ var ts; }); } ts.emitComments = emitComments; - function emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, removeComments) { + function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { if (node.pos === 0) { - leadingComments = ts.filter(ts.getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment); + leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedComment); } } else { - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { var detachedComments = []; @@ -5246,8 +5330,8 @@ var ts; for (var _i = 0, leadingComments_1 = leadingComments; _i < leadingComments_1.length; _i++) { var comment = leadingComments_1[_i]; if (lastComment) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end); - var commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); + var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { break; } @@ -5256,37 +5340,37 @@ var ts; lastComment = comment; } if (detachedComments.length) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, ts.lastOrUndefined(detachedComments).end); - var nodeLine = getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos)); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.lastOrUndefined(detachedComments).end); + var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { - emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - emitComments(currentSourceFile, writer, detachedComments, true, newLine, writeComment); + emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); + emitComments(text, lineMap, writer, detachedComments, true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } } return currentDetachedCommentInfo; function isPinnedComment(comment) { - return currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 33; + return text.charCodeAt(comment.pos + 1) === 42 && + text.charCodeAt(comment.pos + 2) === 33; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(currentSourceFile, writer, comment, newLine) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42) { - var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos); - var lineCount = ts.getLineStarts(currentSourceFile).length; + function writeCommentRange(text, lineMap, writer, comment, newLine) { + if (text.charCodeAt(comment.pos + 1) === 42) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + var lineCount = lineMap.length; var firstCommentLineIndent; for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount - ? currentSourceFile.text.length + 1 - : getStartPositionOfLine(currentLine + 1, currentSourceFile); + ? text.length + 1 + : lineMap[currentLine + 1]; if (pos !== comment.pos) { if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); } var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); - var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart); + var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); @@ -5300,40 +5384,40 @@ var ts; writer.rawWrite(""); } } - writeTrimmedCurrentLine(pos, nextLineStart); + writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { - writer.write(currentSourceFile.text.substring(comment.pos, comment.end)); - } - function writeTrimmedCurrentLine(pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); - var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, ""); - if (currentLineText) { - writer.write(currentLineText); - if (end !== comment.end) { - writer.writeLine(); - } - } - else { - writer.writeLiteral(newLine); - } - } - function calculateIndent(pos, end) { - var currentLineIndent = 0; - for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) { - if (currentSourceFile.text.charCodeAt(pos) === 9) { - currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); - } - else { - currentLineIndent++; - } - } - return currentLineIndent; + writer.write(text.substring(comment.pos, comment.end)); } } ts.writeCommentRange = writeCommentRange; + function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { + var end = Math.min(comment.end, nextLineStart - 1); + var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); + if (currentLineText) { + writer.write(currentLineText); + if (end !== comment.end) { + writer.writeLine(); + } + } + else { + writer.writeLiteral(newLine); + } + } + function calculateIndent(text, pos, end) { + var currentLineIndent = 0; + for (; pos < end && ts.isWhiteSpace(text.charCodeAt(pos)); pos++) { + if (text.charCodeAt(pos) === 9) { + currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); + } + else { + currentLineIndent++; + } + } + return currentLineIndent; + } function modifierToFlag(token) { switch (token) { case 113: return 64; @@ -5427,14 +5511,14 @@ var ts; return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function isJavaScript(fileName) { - return ts.fileExtensionIs(fileName, ".js"); + function hasJavaScriptFileExtension(fileName) { + return ts.fileExtensionIs(fileName, ".js") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isJavaScript = isJavaScript; - function isTsx(fileName) { - return ts.fileExtensionIs(fileName, ".tsx"); + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function allowsJsxExpressions(fileName) { + return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isTsx = isTsx; + ts.allowsJsxExpressions = allowsJsxExpressions; function getExpandedCharCodes(input) { var output = []; var length = input.length; @@ -5644,14 +5728,16 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { - var nodeConstructors = new Array(272); ts.parseTime = 0; - function getNodeConstructor(kind) { - return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)); - } - ts.getNodeConstructor = getNodeConstructor; + var NodeConstructor; + var SourceFileConstructor; function createNode(kind, pos, end) { - return new (getNodeConstructor(kind))(pos, end); + if (kind === 248) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + } + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + } } ts.createNode = createNode; function visitNode(cbNode, node) { @@ -6050,6 +6136,8 @@ var ts; (function (Parser) { var scanner = ts.createScanner(2, true); var disallowInAndDecoratorContext = 1 | 4; + var NodeConstructor; + var SourceFileConstructor; var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -6062,13 +6150,16 @@ var ts; var contextFlags; var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); + var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; + initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; syntaxCursor = _syntaxCursor; parseDiagnostics = []; @@ -6076,12 +6167,12 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = ts.isJavaScript(fileName) ? 32 : 0; + contextFlags = isJavaScriptFile ? 32 : 0; parseErrorBeforeNextFinishedNode = false; scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(ts.isTsx(fileName) ? 1 : 0); + scanner.setLanguageVariant(ts.allowsJsxExpressions(fileName) ? 1 : 0); } function clearState() { scanner.setText(""); @@ -6094,6 +6185,9 @@ var ts; } function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { sourceFile = createSourceFile(fileName, languageVersion); + if (contextFlags & 32) { + sourceFile.parserContextFlags = 32; + } token = nextToken(); processReferenceComments(sourceFile); sourceFile.statements = parseList(0, parseStatement); @@ -6107,7 +6201,7 @@ var ts; if (setParentNodes) { fixupParentReferences(sourceFile); } - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { addJSDocComments(); } return sourceFile; @@ -6153,15 +6247,14 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion) { - var sourceFile = createNode(248, 0); - sourceFile.pos = 0; - sourceFile.end = sourceText.length; + var sourceFile = new SourceFileConstructor(248, 0, sourceText.length); + nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 : 0; - sourceFile.languageVariant = ts.isTsx(sourceFile.fileName) ? 1 : 0; + sourceFile.languageVariant = ts.allowsJsxExpressions(sourceFile.fileName) ? 1 : 0; return sourceFile; } function setContextFlag(val, flag) { @@ -6383,7 +6476,7 @@ var ts; if (!(pos >= 0)) { pos = scanner.getStartPos(); } - return new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))(pos, pos); + return new NodeConstructor(kind, pos, pos); } function finishNode(node, end) { node.end = end === undefined ? scanner.getStartPos() : end; @@ -6521,7 +6614,7 @@ var ts; case 12: return token === 19 || token === 37 || isLiteralPropertyName(); case 9: - return isLiteralPropertyName(); + return token === 19 || isLiteralPropertyName(); case 7: if (token === 15) { return lookAhead(isValidHeritageClauseObjectLiteral); @@ -7042,9 +7135,7 @@ var ts; } function parseParameterType() { if (parseOptional(54)) { - return token === 9 - ? parseLiteralNode(true) - : parseType(); + return parseType(); } return undefined; } @@ -7301,6 +7392,8 @@ var ts; case 131: var node = tryParse(parseKeywordAndNoDot); return node || parseTypeReferenceOrTypePredicate(); + case 9: + return parseLiteralNode(true); case 103: case 97: return parseTokenNode(); @@ -7330,6 +7423,7 @@ var ts; case 19: case 25: case 92: + case 9: return true; case 17: return lookAhead(isStartOfParenthesizedOrFunctionType); @@ -7843,7 +7937,6 @@ var ts; var unaryOperator = token; var simpleUnaryExpression = parseSimpleUnaryExpression(); if (token === 38) { - var diagnostic; var start = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); if (simpleUnaryExpression.kind === 171) { parseErrorAtPosition(start, simpleUnaryExpression.end - start, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); @@ -9507,7 +9600,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2, undefined); + initializeState("file.js", content, 2, true, undefined); var jsDocTypeExpression = parseJSDocTypeExpression(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -9758,7 +9851,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2, undefined); + initializeState("file.js", content, 2, true, undefined); var jsDocComment = parseJSDocComment(undefined, start, length); var diagnostics = parseDiagnostics; clearState(); @@ -10394,6 +10487,9 @@ var ts; } if (node.name.kind === 136) { var nameExpression = node.name.expression; + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; + } ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); } @@ -10414,6 +10510,8 @@ var ts; return "__export"; case 227: return node.isExportEquals ? "export=" : "default"; + case 181: + return "export="; case 213: case 214: return node.flags & 512 ? "default" : undefined; @@ -11033,6 +11131,14 @@ var ts; case 69: return checkStrictModeIdentifier(node); case 181: + if (ts.isInJavaScriptFile(node)) { + if (ts.isExportsPropertyAssignment(node)) { + bindExportsPropertyAssignment(node); + } + else if (ts.isModuleExportsAssignment(node)) { + bindModuleExportsAssignment(node); + } + } return checkStrictModeBinaryExpression(node); case 244: return checkStrictModeCatchClause(node); @@ -11092,6 +11198,11 @@ var ts; checkStrictModeFunctionName(node); var bindingName = node.name ? node.name.text : "__function"; return bindAnonymousDeclaration(node, 16, bindingName); + case 168: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; case 186: case 214: return bindClassLikeDeclaration(node); @@ -11121,14 +11232,18 @@ var ts; function bindSourceFileIfExternalModule() { setExportContextFlag(file); if (ts.isExternalModule(file)) { - bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); + bindSourceFileAsExternalModule(); } } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } function bindExportAssignment(node) { + var boundExpression = node.kind === 227 ? node.expression : node.right; if (!container.symbol || !container.symbol.exports) { bindAnonymousDeclaration(node, 8388608, getDeclarationName(node)); } - else if (node.expression.kind === 69) { + else if (boundExpression.kind === 69) { declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 107455 | 8388608); } else { @@ -11148,6 +11263,25 @@ var ts; declareSymbolAndAddToSymbolTable(node, 8388608, 8388608); } } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); + } + } + function bindExportsPropertyAssignment(node) { + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 | 7340032, 0); + } + function bindModuleExportsAssignment(node) { + setCommonJsModuleIndicator(node); + bindExportAssignment(node); + } + function bindCallExpression(node) { + if (!file.commonJsModuleIndicator && ts.isRequireCall(node)) { + setCommonJsModuleIndicator(node); + } + } function bindClassLikeDeclaration(node) { if (node.kind === 214) { bindBlockScopedDeclaration(node, 32, 899519); @@ -11268,7 +11402,7 @@ var ts; function checkUnreachable(node) { switch (currentReachabilityState) { case 4: - var reportError = ts.isStatement(node) || + var reportError = (ts.isStatement(node) && node.kind !== 194) || node.kind === 214 || (node.kind === 218 && shouldReportErrorOnModuleDeclaration(node)) || (node.kind === 217 && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); @@ -11364,7 +11498,7 @@ var ts; symbolToString: symbolToString, getAugmentedPropertiesOfType: getAugmentedPropertiesOfType, getRootSymbols: getRootSymbols, - getContextualType: getContextualType, + getContextualType: getApparentTypeOfContextualType, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: getResolvedSignature, getConstantValue: getConstantValue, @@ -11620,7 +11754,7 @@ var ts; return ts.getAncestor(node, 248); } function isGlobalSourceFile(node) { - return node.kind === 248 && !ts.isExternalModule(node); + return node.kind === 248 && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning && ts.hasProperty(symbols, name)) { @@ -11706,23 +11840,24 @@ var ts; } switch (location.kind) { case 248: - if (!ts.isExternalModule(location)) + if (!ts.isExternalOrCommonJsModule(location)) break; case 218: var moduleExports = getSymbolOfNode(location).exports; if (location.kind === 248 || (location.kind === 218 && location.name.kind === 9)) { + if (result = moduleExports["default"]) { + var localSymbol = ts.getLocalSymbolForExportDefault(result); + if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { + break loop; + } + result = undefined; + } if (ts.hasProperty(moduleExports, name) && moduleExports[name].flags === 8388608 && ts.getDeclarationOfKind(moduleExports[name], 230)) { break; } - result = moduleExports["default"]; - var localSymbol = ts.getLocalSymbolForExportDefault(result); - if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) { - break loop; - } - result = undefined; } if (result = getSymbol(moduleExports, name, meaning & 8914931)) { break loop; @@ -12080,6 +12215,9 @@ var ts; if (moduleName === undefined) { return; } + if (moduleName.indexOf("!") >= 0) { + moduleName = moduleName.substr(0, moduleName.indexOf("!")); + } var isRelative = ts.isExternalModuleNameRelative(moduleName); if (!isRelative) { var symbol = getSymbol(globals, "\"" + moduleName + "\"", 512); @@ -12250,7 +12388,7 @@ var ts; } switch (location_1.kind) { case 248: - if (!ts.isExternalModule(location_1)) { + if (!ts.isExternalOrCommonJsModule(location_1)) { break; } case 218: @@ -12377,7 +12515,7 @@ var ts; } function hasExternalModuleSymbol(declaration) { return (declaration.kind === 218 && declaration.name.kind === 9) || - (declaration.kind === 248 && ts.isExternalModule(declaration)); + (declaration.kind === 248 && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol) { var aliasesToMakeVisible; @@ -12575,7 +12713,7 @@ var ts; writeAnonymousType(type, flags); } else if (type.flags & 256) { - writer.writeStringLiteral(type.text); + writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); } else { writePunctuation(writer, 15); @@ -12939,7 +13077,7 @@ var ts; } } else if (node.kind === 248) { - return ts.isExternalModule(node) ? node : undefined; + return ts.isExternalOrCommonJsModule(node) ? node : undefined; } } ts.Debug.fail("getContainingModule cant reach here"); @@ -13144,6 +13282,23 @@ var ts; var symbol = getSymbolOfNode(node); return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node); } + function getTextOfPropertyName(name) { + switch (name.kind) { + case 69: + return name.text; + case 9: + case 8: + return name.text; + case 136: + if (ts.isStringOrNumericLiteral(name.expression.kind)) { + return name.expression.text; + } + } + return undefined; + } + function isComputedNonLiteralName(name) { + return name.kind === 136 && !ts.isStringOrNumericLiteral(name.expression.kind); + } function getTypeForBindingElement(declaration) { var pattern = declaration.parent; var parentType = getTypeForBindingElementParent(pattern.parent); @@ -13159,8 +13314,12 @@ var ts; var type; if (pattern.kind === 161) { var name_11 = declaration.propertyName || declaration.name; - type = getTypeOfPropertyOfType(parentType, name_11.text) || - isNumericLiteralName(name_11.text) && getIndexTypeOfType(parentType, 1) || + if (isComputedNonLiteralName(name_11)) { + return anyType; + } + var text = getTextOfPropertyName(name_11); + type = getTypeOfPropertyOfType(parentType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1) || getIndexTypeOfType(parentType, 0); if (!type) { error(name_11, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_11)); @@ -13238,10 +13397,16 @@ var ts; } function getTypeFromObjectBindingPattern(pattern, includePatternInType) { var members = {}; + var hasComputedProperties = false; ts.forEach(pattern.elements, function (e) { - var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0); var name = e.propertyName || e.name; - var symbol = createSymbol(flags, name.text); + if (isComputedNonLiteralName(name)) { + hasComputedProperties = true; + return; + } + var text = getTextOfPropertyName(name); + var flags = 4 | 67108864 | (e.initializer ? 536870912 : 0); + var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType); symbol.bindingElement = e; members[symbol.name] = symbol; @@ -13250,6 +13415,9 @@ var ts; if (includePatternInType) { result.pattern = pattern; } + if (hasComputedProperties) { + result.flags |= 67108864; + } return result; } function getTypeFromArrayBindingPattern(pattern, includePatternInType) { @@ -13300,6 +13468,12 @@ var ts; if (declaration.kind === 227) { return links.type = checkExpression(declaration.expression); } + if (declaration.kind === 181) { + return links.type = checkExpression(declaration.right); + } + if (declaration.kind === 166) { + return checkExpressionCached(declaration.parent.right); + } if (!pushTypeResolution(symbol, 0)) { return unknownType; } @@ -13549,17 +13723,19 @@ var ts; } function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - var baseContructorType = getBaseConstructorTypeOfClass(type); - if (!(baseContructorType.flags & 80896)) { + var baseConstructorType = getBaseConstructorTypeOfClass(type); + if (!(baseConstructorType.flags & 80896)) { return; } var baseTypeNode = getBaseTypeNodeOfClass(type); var baseType; - if (baseContructorType.symbol && baseContructorType.symbol.flags & 32) { - baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol); + var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 && + areAllOuterTypeParametersApplied(originalBaseType)) { + baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } else { - var constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments); + var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); return; @@ -13584,6 +13760,15 @@ var ts; type.resolvedBaseTypes.push(baseType); } } + function areAllOuterTypeParametersApplied(type) { + var outerTypeParameters = type.outerTypeParameters; + if (outerTypeParameters) { + var last = outerTypeParameters.length - 1; + var typeArguments = type.typeArguments; + return outerTypeParameters[last].symbol !== typeArguments[last].symbol; + } + return true; + } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { @@ -13655,7 +13840,7 @@ var ts; type.typeArguments = type.typeParameters; type.thisType = createType(512 | 33554432); type.thisType.symbol = symbol; - type.thisType.constraint = getTypeWithThisArgument(type); + type.thisType.constraint = type; } } return links.declaredType; @@ -14130,14 +14315,19 @@ var ts; type = getApparentType(type); return type.flags & 49152 ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } + function getApparentTypeOfTypeParameter(type) { + if (!type.resolvedApparentType) { + var constraintType = getConstraintOfTypeParameter(type); + while (constraintType && constraintType.flags & 512) { + constraintType = getConstraintOfTypeParameter(constraintType); + } + type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type); + } + return type.resolvedApparentType; + } function getApparentType(type) { if (type.flags & 512) { - do { - type = getConstraintOfTypeParameter(type); - } while (type && type.flags & 512); - if (!type) { - type = emptyObjectType; - } + type = getApparentTypeOfTypeParameter(type); } if (type.flags & 258) { type = globalStringType; @@ -14290,7 +14480,7 @@ var ts; if (node.initializer) { var signatureDeclaration = node.parent; var signature = getSignatureFromDeclaration(signatureDeclaration); - var parameterIndex = signatureDeclaration.parameters.indexOf(node); + var parameterIndex = ts.indexOf(signatureDeclaration.parameters, node); ts.Debug.assert(parameterIndex >= 0); return parameterIndex >= signature.minArgumentCount; } @@ -14385,6 +14575,16 @@ var ts; } return result; } + function resolveExternalModuleTypeByLiteral(name) { + var moduleSym = resolveExternalModuleName(name, name); + if (moduleSym) { + var resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + return getTypeOfSymbol(resolvedModuleSymbol); + } + } + return anyType; + } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { if (!pushTypeResolution(signature, 3)) { @@ -14846,11 +15046,12 @@ var ts; return links.resolvedType; } function getStringLiteralType(node) { - if (ts.hasProperty(stringLiteralTypes, node.text)) { - return stringLiteralTypes[node.text]; + var text = node.text; + if (ts.hasProperty(stringLiteralTypes, text)) { + return stringLiteralTypes[text]; } - var type = stringLiteralTypes[node.text] = createType(256); - type.text = ts.getTextOfNode(node); + var type = stringLiteralTypes[text] = createType(256); + type.text = text; return type; } function getTypeFromStringLiteral(node) { @@ -15319,7 +15520,7 @@ var ts; return false; } function hasExcessProperties(source, target, reportErrors) { - if (someConstituentTypeHasKind(target, 80896)) { + if (!(target.flags & 67108864) && someConstituentTypeHasKind(target, 80896)) { for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (!isKnownProperty(target, prop.name)) { @@ -15409,9 +15610,6 @@ var ts; return result; } function typeParameterIdenticalTo(source, target) { - if (source.symbol.name !== target.symbol.name) { - return 0; - } if (source.constraint === target.constraint) { return -1; } @@ -15856,18 +16054,24 @@ var ts; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } + function isMatchingSignature(source, target, partialMatch) { + if (source.parameters.length === target.parameters.length && + source.minArgumentCount === target.minArgumentCount && + source.hasRestParameter === target.hasRestParameter) { + return true; + } + if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (source.hasRestParameter && !target.hasRestParameter || + source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) { + return true; + } + return false; + } function compareSignatures(source, target, partialMatch, ignoreReturnTypes, compareTypes) { if (source === target) { return -1; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { - if (!partialMatch || - source.parameters.length < target.parameters.length && !source.hasRestParameter || - source.minArgumentCount > target.minArgumentCount) { - return 0; - } + if (!(isMatchingSignature(source, target, partialMatch))) { + return 0; } var result = -1; if (source.typeParameters && target.typeParameters) { @@ -15952,6 +16156,9 @@ var ts; function isTupleLikeType(type) { return !!getPropertyOfType(type, "0"); } + function isStringLiteralType(type) { + return type.flags & 256; + } function isTupleType(type) { return !!(type.flags & 8192); } @@ -16543,7 +16750,7 @@ var ts; } } function narrowTypeByInstanceof(type, expr, assumeTrue) { - if (isTypeAny(type) || !assumeTrue || expr.left.kind !== 69 || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || expr.left.kind !== 69 || getResolvedSymbol(expr.left) !== symbol) { return type; } var rightType = checkExpression(expr.right); @@ -16571,6 +16778,12 @@ var ts; } } if (targetType) { + if (!assumeTrue) { + if (type.flags & 16384) { + return getUnionType(ts.filter(type.types, function (t) { return !isTypeSubtypeOf(t, targetType); })); + } + return type; + } return getNarrowedType(type, targetType); } return type; @@ -16982,6 +17195,9 @@ var ts; function getIndexTypeOfContextualType(type, kind) { return applyToContextualType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }); } + function contextualTypeIsStringLiteralType(type) { + return !!(type.flags & 16384 ? ts.forEach(type.types, isStringLiteralType) : isStringLiteralType(type)); + } function contextualTypeIsTupleLikeType(type) { return !!(type.flags & 16384 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); } @@ -16997,7 +17213,7 @@ var ts; } function getContextualTypeForObjectLiteralElement(element) { var objectLiteral = element.parent; - var type = getContextualType(objectLiteral); + var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!ts.hasDynamicName(element)) { var symbolName = getSymbolOfNode(element).name; @@ -17013,7 +17229,7 @@ var ts; } function getContextualTypeForElementExpression(node) { var arrayLiteral = node.parent; - var type = getContextualType(arrayLiteral); + var type = getApparentTypeOfContextualType(arrayLiteral); if (type) { var index = ts.indexOf(arrayLiteral.elements, node); return getTypeOfPropertyOfContextualType(type, "" + index) @@ -17042,11 +17258,11 @@ var ts; } return undefined; } - function getContextualType(node) { - var type = getContextualTypeWorker(node); + function getApparentTypeOfContextualType(node) { + var type = getContextualType(node); return type && getApparentType(type); } - function getContextualTypeWorker(node) { + function getContextualType(node) { if (isInsideWithStatementBody(node)) { return undefined; } @@ -17112,7 +17328,7 @@ var ts; ts.Debug.assert(node.kind !== 143 || ts.isObjectLiteralMethod(node)); var type = ts.isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node) - : getContextualType(node); + : getApparentTypeOfContextualType(node); if (!type) { return undefined; } @@ -17195,7 +17411,7 @@ var ts; type.pattern = node; return type; } - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; if (pattern && (pattern.kind === 162 || pattern.kind === 164)) { @@ -17250,10 +17466,11 @@ var ts; checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable = {}; var propertiesArray = []; - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === 161 || contextualType.pattern.kind === 165); var typeFlags = 0; + var patternWithComputedProperties = false; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var memberDecl = _a[_i]; var member = memberDecl.symbol; @@ -17279,8 +17496,11 @@ var ts; if (isOptional) { prop.flags |= 536870912; } + if (ts.hasDynamicName(memberDecl)) { + patternWithComputedProperties = true; + } } - else if (contextualTypeHasPattern) { + else if (contextualTypeHasPattern && !(contextualType.flags & 67108864)) { var impliedProp = getPropertyOfType(contextualType, member.name); if (impliedProp) { prop.flags |= impliedProp.flags & 536870912; @@ -17323,7 +17543,7 @@ var ts; var numberIndexType = getIndexType(1); var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType); var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 1048576; - result.flags |= 524288 | 4194304 | freshObjectLiteralFlag | (typeFlags & 14680064); + result.flags |= 524288 | 4194304 | freshObjectLiteralFlag | (typeFlags & 14680064) | (patternWithComputedProperties ? 67108864 : 0); if (inDestructuringPattern) { result.pattern = node; } @@ -18538,6 +18758,9 @@ var ts; return anyType; } } + if (ts.isInJavaScriptFile(node) && ts.isRequireCall(node)) { + return resolveExternalModuleTypeByLiteral(node.arguments[0]); + } return getReturnTypeOfSignature(signature); } function checkTaggedTemplateExpression(node) { @@ -18548,7 +18771,9 @@ var ts; var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { var widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { + var bothAreStringLike = someConstituentTypeHasKind(targetType, 258) && + someConstituentTypeHasKind(widenedType, 258); + if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } @@ -18987,17 +19212,24 @@ var ts; var p = properties_3[_i]; if (p.kind === 245 || p.kind === 246) { var name_14 = p.name; + if (name_14.kind === 136) { + checkComputedPropertyName(name_14); + } + if (isComputedNonLiteralName(name_14)) { + continue; + } + var text = getTextOfPropertyName(name_14); var type = isTypeAny(sourceType) ? sourceType - : getTypeOfPropertyOfType(sourceType, name_14.text) || - isNumericLiteralName(name_14.text) && getIndexTypeOfType(sourceType, 1) || + : getTypeOfPropertyOfType(sourceType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(sourceType, 1) || getIndexTypeOfType(sourceType, 0); if (type) { if (p.kind === 246) { checkDestructuringAssignment(p, type); } else { - checkDestructuringAssignment(p.initializer || name_14, type); + checkDestructuringAssignment(p.initializer, type); } } else { @@ -19175,6 +19407,9 @@ var ts; case 31: case 32: case 33: + if (someConstituentTypeHasKind(leftType, 258) && someConstituentTypeHasKind(rightType, 258)) { + return booleanType; + } if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { reportOperatorError(); } @@ -19282,6 +19517,13 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getUnionType([type1, type2]); } + function checkStringLiteralExpression(node) { + var contextualType = getContextualType(node); + if (contextualType && contextualTypeIsStringLiteralType(contextualType)) { + return getStringLiteralType(node); + } + return stringType; + } function checkTemplateExpression(node) { ts.forEach(node.templateSpans, function (templateSpan) { checkExpression(templateSpan.expression); @@ -19320,7 +19562,7 @@ var ts; if (isInferentialContext(contextualMapper)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(contextualType); if (contextualSignature && !contextualSignature.typeParameters) { @@ -19372,6 +19614,7 @@ var ts; case 183: return checkTemplateExpression(node); case 9: + return checkStringLiteralExpression(node); case 11: return stringType; case 10: @@ -20433,7 +20676,7 @@ var ts; return; } var parent = getDeclarationContainer(node); - if (parent.kind === 248 && ts.isExternalModule(parent)) { + if (parent.kind === 248 && ts.isExternalOrCommonJsModule(parent)) { error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } @@ -20504,6 +20747,11 @@ var ts; checkExpressionCached(node.initializer); } } + if (node.kind === 163) { + if (node.propertyName && node.propertyName.kind === 136) { + checkComputedPropertyName(node.propertyName); + } + } if (ts.isBindingPattern(node.name)) { ts.forEach(node.name.elements, checkSourceElement); } @@ -20862,6 +21110,7 @@ var ts; var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); + var expressionTypeIsStringLike = someConstituentTypeHasKind(expressionType, 258); ts.forEach(node.caseBlock.clauses, function (clause) { if (clause.kind === 242 && !hasDuplicateDefaultClause) { if (firstDefaultClause === undefined) { @@ -20878,6 +21127,9 @@ var ts; if (produceDiagnostics && clause.kind === 241) { var caseClause = clause; var caseType = checkExpression(caseClause.expression); + if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, 258)) { + return; + } if (!isTypeAssignableTo(expressionType, caseType)) { checkTypeAssignableTo(caseType, expressionType, caseClause.expression, undefined); } @@ -21285,11 +21537,14 @@ var ts; var enumIsConst = ts.isConst(node); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.name.kind === 136) { + if (isComputedNonLiteralName(member.name)) { error(member.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums); } - else if (isNumericLiteralName(member.name.text)) { - error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + else { + var text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text)) { + error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + } } var previousEnumMemberIsNonConstant = autoValue === undefined; var initializer = member.initializer; @@ -21987,8 +22242,10 @@ var ts; function checkSourceFileWorker(node) { var links = getNodeLinks(node); if (!(links.flags & 1)) { - if (node.isDefaultLib && compilerOptions.skipDefaultLibCheck) { - return; + if (compilerOptions.skipDefaultLibCheck) { + if (node.hasNoDefaultLib) { + return; + } } checkGrammarSourceFile(node); emitExtends = false; @@ -21997,7 +22254,7 @@ var ts; potentialThisCollisions.length = 0; ts.forEach(node.statements, checkSourceElement); checkFunctionAndClassExpressionBodies(node); - if (ts.isExternalModule(node)) { + if (ts.isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); } if (potentialThisCollisions.length) { @@ -22075,7 +22332,7 @@ var ts; } switch (location.kind) { case 248: - if (!ts.isExternalModule(location)) { + if (!ts.isExternalOrCommonJsModule(location)) { break; } case 218: @@ -22634,15 +22891,24 @@ var ts; getReferencedValueDeclaration: getReferencedValueDeclaration, getTypeReferenceSerializationKind: getTypeReferenceSerializationKind, isOptionalParameter: isOptionalParameter, - isArgumentsLocalBinding: isArgumentsLocalBinding + isArgumentsLocalBinding: isArgumentsLocalBinding, + getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration }; } + function getExternalModuleFileFromDeclaration(declaration) { + var specifier = ts.getExternalModuleName(declaration); + var moduleSymbol = getSymbolAtLocation(specifier); + if (!moduleSymbol) { + return undefined; + } + return ts.getDeclarationOfKind(moduleSymbol, 248); + } function initializeTypeChecker() { ts.forEach(host.getSourceFiles(), function (file) { ts.bindSourceFile(file, compilerOptions); }); ts.forEach(host.getSourceFiles(), function (file) { - if (!ts.isExternalModule(file)) { + if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } }); @@ -23319,7 +23585,7 @@ var ts; } } function checkGrammarForNonSymbolComputedProperty(node, message) { - if (node.kind === 136 && !ts.isWellKnownSymbolSyntactically(node.expression)) { + if (ts.isDynamicName(node)) { return grammarErrorOnNode(node, message); } } @@ -23633,11 +23899,15 @@ var ts; var writeTextOfNode; var writer = createAndSetNewTextWriterWithSymbolWriter(); var enclosingDeclaration; - var currentSourceFile; + var currentText; + var currentLineMap; + var currentIdentifiers; + var isCurrentFileExternalModule; var reportedDeclarationError = false; var errorNameNode; var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments; var emit = compilerOptions.stripInternal ? stripInternal : emitNode; + var noDeclare = !root; var moduleElementDeclarationEmitInfo = []; var asynchronousSubModuleDeclarationEmitInfo; var referencePathsOutput = ""; @@ -23673,21 +23943,53 @@ var ts; } else { var emittedReferencedFiles = []; + var prevModuleElementDeclarationEmitInfo = []; ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + if (!ts.isDeclarationFile(sourceFile)) { if (!compilerOptions.noResolve) { ts.forEach(sourceFile.referencedFiles, function (fileReference) { var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference); - if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) && + if (referencedFile && (ts.isDeclarationFile(referencedFile) && !ts.contains(emittedReferencedFiles, referencedFile))) { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); } }); } + } + if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + noDeclare = false; emitSourceFile(sourceFile); } + else if (ts.isExternalModule(sourceFile)) { + noDeclare = true; + write("declare module \"" + ts.getResolvedExternalModuleName(host, sourceFile) + "\" {"); + writeLine(); + increaseIndent(); + emitSourceFile(sourceFile); + decreaseIndent(); + write("}"); + writeLine(); + if (moduleElementDeclarationEmitInfo.length) { + var oldWriter = writer; + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.isVisible && !aliasEmitInfo.asynchronousOutput) { + ts.Debug.assert(aliasEmitInfo.node.kind === 222); + createAndSetNewTextWriterWithSymbolWriter(); + ts.Debug.assert(aliasEmitInfo.indent === 1); + increaseIndent(); + writeImportDeclaration(aliasEmitInfo.node); + aliasEmitInfo.asynchronousOutput = writer.getText(); + decreaseIndent(); + } + }); + setWriter(oldWriter); + } + prevModuleElementDeclarationEmitInfo = prevModuleElementDeclarationEmitInfo.concat(moduleElementDeclarationEmitInfo); + moduleElementDeclarationEmitInfo = []; + } }); + moduleElementDeclarationEmitInfo = moduleElementDeclarationEmitInfo.concat(prevModuleElementDeclarationEmitInfo); } return { reportedDeclarationError: reportedDeclarationError, @@ -23696,13 +23998,12 @@ var ts; referencePathsOutput: referencePathsOutput }; function hasInternalAnnotation(range) { - var text = currentSourceFile.text; - var comment = text.substring(range.pos, range.end); + var comment = currentText.substring(range.pos, range.end); return comment.indexOf("@internal") >= 0; } function stripInternal(node) { if (node) { - var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + var leadingCommentRanges = ts.getLeadingCommentRanges(currentText, node.pos); if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) { return; } @@ -23783,7 +24084,7 @@ var ts; var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult); if (errorInfo) { if (errorInfo.typeName) { - diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); + diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); } else { diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); @@ -23847,9 +24148,9 @@ var ts; } function writeJsDocComments(declaration) { if (declaration) { - var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile); - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments); - ts.emitComments(currentSourceFile, writer, jsDocComments, true, newLine, ts.writeCommentRange); + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, true, newLine, ts.writeCommentRange); } } function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { @@ -23866,7 +24167,7 @@ var ts; case 103: case 97: case 9: - return writeTextOfNode(currentSourceFile, type); + return writeTextOfNode(currentText, type); case 188: return emitExpressionWithTypeArguments(type); case 151: @@ -23897,14 +24198,14 @@ var ts; } function writeEntityName(entityName) { if (entityName.kind === 69) { - writeTextOfNode(currentSourceFile, entityName); + writeTextOfNode(currentText, entityName); } else { var left = entityName.kind === 135 ? entityName.left : entityName.expression; var right = entityName.kind === 135 ? entityName.right : entityName.name; writeEntityName(left); write("."); - writeTextOfNode(currentSourceFile, right); + writeTextOfNode(currentText, right); } } function emitEntityName(entityName) { @@ -23932,7 +24233,7 @@ var ts; } } function emitTypePredicate(type) { - writeTextOfNode(currentSourceFile, type.parameterName); + writeTextOfNode(currentText, type.parameterName); write(" is "); emitType(type.type); } @@ -23972,20 +24273,23 @@ var ts; } } function emitSourceFile(node) { - currentSourceFile = node; + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); enclosingDeclaration = node; - ts.emitDetachedComments(currentSourceFile, writer, ts.writeCommentRange, node, newLine, true); + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true); emitLines(node.statements); } function getExportDefaultTempVariableName() { var baseName = "_default"; - if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) { + if (!ts.hasProperty(currentIdentifiers, baseName)) { return baseName; } var count = 0; while (true) { var name_19 = baseName + "_" + (++count); - if (!ts.hasProperty(currentSourceFile.identifiers, name_19)) { + if (!ts.hasProperty(currentIdentifiers, name_19)) { return name_19; } } @@ -23993,7 +24297,7 @@ var ts; function emitExportAssignment(node) { if (node.expression.kind === 69) { write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentSourceFile, node.expression); + writeTextOfNode(currentText, node.expression); } else { var tempVarName = getExportDefaultTempVariableName(); @@ -24028,7 +24332,7 @@ var ts; writeModuleElement(node); } else if (node.kind === 221 || - (node.parent.kind === 248 && ts.isExternalModule(currentSourceFile))) { + (node.parent.kind === 248 && isCurrentFileExternalModule)) { var isVisible; if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 248) { asynchronousSubModuleDeclarationEmitInfo.push({ @@ -24080,14 +24384,14 @@ var ts; } } function emitModuleElementDeclarationFlags(node) { - if (node.parent === currentSourceFile) { + if (node.parent.kind === 248) { if (node.flags & 2) { write("export "); } if (node.flags & 512) { write("default "); } - else if (node.kind !== 215) { + else if (node.kind !== 215 && !noDeclare) { write("declare "); } } @@ -24112,7 +24416,7 @@ var ts; write("export "); } write("import "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" = "); if (ts.isInternalModuleImportEqualsDeclaration(node)) { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); @@ -24120,7 +24424,7 @@ var ts; } else { write("require("); - writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node)); + writeTextOfNode(currentText, ts.getExternalModuleImportEqualsDeclarationExpression(node)); write(");"); } writer.writeLine(); @@ -24154,7 +24458,7 @@ var ts; if (node.importClause) { var currentWriterPos = writer.getTextPos(); if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentSourceFile, node.importClause.name); + writeTextOfNode(currentText, node.importClause.name); } if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { if (currentWriterPos !== writer.getTextPos()) { @@ -24162,7 +24466,7 @@ var ts; } if (node.importClause.namedBindings.kind === 224) { write("* as "); - writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name); + writeTextOfNode(currentText, node.importClause.namedBindings.name); } else { write("{ "); @@ -24172,16 +24476,28 @@ var ts; } write(" from "); } - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); write(";"); writer.writeLine(); } + function emitExternalModuleSpecifier(moduleSpecifier) { + if (moduleSpecifier.kind === 9 && (!root) && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, moduleSpecifier.parent); + if (moduleName) { + write("\""); + write(moduleName); + write("\""); + return; + } + } + writeTextOfNode(currentText, moduleSpecifier); + } function emitImportOrExportSpecifier(node) { if (node.propertyName) { - writeTextOfNode(currentSourceFile, node.propertyName); + writeTextOfNode(currentText, node.propertyName); write(" as "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } function emitExportSpecifier(node) { emitImportOrExportSpecifier(node); @@ -24201,7 +24517,7 @@ var ts; } if (node.moduleSpecifier) { write(" from "); - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); } write(";"); writer.writeLine(); @@ -24215,11 +24531,11 @@ var ts; else { write("module "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); while (node.body.kind !== 219) { node = node.body; write("."); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; @@ -24238,7 +24554,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); @@ -24260,7 +24576,7 @@ var ts; write("const "); } write("enum "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" {"); writeLine(); increaseIndent(); @@ -24271,7 +24587,7 @@ var ts; } function emitEnumMemberDeclaration(node) { emitJsDocComments(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var enumMemberValue = resolver.getConstantValue(node); if (enumMemberValue !== undefined) { write(" = "); @@ -24288,7 +24604,7 @@ var ts; increaseIndent(); emitJsDocComments(node); decreaseIndent(); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (node.constraint && !isPrivateMethodTypeParameter(node)) { write(" extends "); if (node.parent.kind === 152 || @@ -24398,7 +24714,7 @@ var ts; write("abstract "); } write("class "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -24421,7 +24737,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("interface "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -24451,7 +24767,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if ((node.kind === 141 || node.kind === 140) && ts.hasQuestionToken(node)) { write("?"); } @@ -24525,7 +24841,7 @@ var ts; emitBindingPattern(bindingElement.name); } else { - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); writeTypeOfDeclaration(bindingElement, undefined, getBindingElementTypeVisibilityError); } } @@ -24566,7 +24882,7 @@ var ts; emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.setAccessor); emitClassMemberDeclarationFlags(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (!(node.flags & 16)) { accessorWithTypeAnnotation = node; var type = getTypeAnnotationFromAccessor(node); @@ -24647,13 +24963,13 @@ var ts; } if (node.kind === 213) { write("function "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } else if (node.kind === 144) { write("constructor"); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (ts.hasQuestionToken(node)) { write("?"); } @@ -24766,7 +25082,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } if (resolver.isOptionalParameter(node)) { write("?"); @@ -24865,7 +25181,7 @@ var ts; } else if (bindingElement.kind === 163) { if (bindingElement.propertyName) { - writeTextOfNode(currentSourceFile, bindingElement.propertyName); + writeTextOfNode(currentText, bindingElement.propertyName); write(": "); } if (bindingElement.name) { @@ -24877,7 +25193,7 @@ var ts; if (bindingElement.dotDotDotToken) { write("..."); } - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); } } } @@ -24960,6 +25276,18 @@ var ts; return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile); } ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || ts.isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; var entities = { "quot": 0x0022, "amp": 0x0026, @@ -25229,15 +25557,19 @@ var ts; var newLine = host.getNewLine(); var jsxDesugaring = host.getCompilerOptions().jsx !== 1; var shouldEmitJsx = function (s) { return (s.languageVariant === 1 && !jsxDesugaring); }; + var outFile = compilerOptions.outFile || compilerOptions.out; + var emitJavaScript = createFileEmitter(); if (targetSourceFile === undefined) { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { - var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); - emitFile(jsFilePath, sourceFile); - } - }); - if (compilerOptions.outFile || compilerOptions.out) { - emitFile(compilerOptions.outFile || compilerOptions.out); + if (outFile) { + emitFile(outFile); + } + else { + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { + var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); + emitFile(jsFilePath, sourceFile); + } + }); } } else { @@ -25245,8 +25577,8 @@ var ts; var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js"); emitFile(jsFilePath, targetSourceFile); } - else if (!ts.isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) { - emitFile(compilerOptions.outFile || compilerOptions.out); + else if (!ts.isDeclarationFile(targetSourceFile) && outFile) { + emitFile(outFile); } } diagnostics = ts.sortAndDeduplicateDiagnostics(diagnostics); @@ -25296,20 +25628,26 @@ var ts; } } } - function emitJavaScript(jsFilePath, root) { + function createFileEmitter() { var writer = ts.createTextWriter(newLine); var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; var currentSourceFile; + var currentText; + var currentLineMap; + var currentFileIdentifiers; + var renamedDependencies; + var isEs6Module; + var isCurrentFileExternalModule; var exportFunctionForFile; - var generatedNameSet = {}; - var nodeToGeneratedName = []; + var generatedNameSet; + var nodeToGeneratedName; var computedPropertyNamesToGeneratedNames; var convertedLoopState; - var extendsEmitted = false; - var decorateEmitted = false; - var paramEmitted = false; - var awaiterEmitted = false; - var tempFlags = 0; + var extendsEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var tempFlags; var tempVariables; var tempParameters; var externalImports; @@ -25326,6 +25664,7 @@ var ts; var scopeEmitStart = function (scopeDeclaration, scopeName) { }; var scopeEmitEnd = function () { }; var sourceMapData; + var root; var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; var moduleEmitDelegates = (_a = {}, _a[5] = emitES6Module, @@ -25335,30 +25674,75 @@ var ts; _a[1] = emitCommonJSModule, _a ); - if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { - initializeEmitterWithSourceMaps(); - } - if (root) { - emitSourceFile(root); - } - else { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - emitSourceFile(sourceFile); + var bundleEmitDelegates = (_b = {}, + _b[5] = function () { }, + _b[2] = emitAMDModule, + _b[4] = emitSystemModule, + _b[3] = function () { }, + _b[1] = function () { }, + _b + ); + return doEmit; + function doEmit(jsFilePath, rootFile) { + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = {}; + nodeToGeneratedName = []; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = rootFile; + if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { + initializeEmitterWithSourceMaps(jsFilePath, root); + } + if (root) { + emitSourceFile(root); + } + else { + if (modulekind) { + ts.forEach(host.getSourceFiles(), emitEmitHelpers); } - }); + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if ((!isExternalModuleOrDeclarationFile(sourceFile)) || (modulekind && ts.isExternalModule(sourceFile))) { + emitSourceFile(sourceFile); + } + }); + } + writeLine(); + writeEmittedFiles(writer.getText(), jsFilePath, compilerOptions.emitBOM); } - writeLine(); - writeEmittedFiles(writer.getText(), compilerOptions.emitBOM); - return; function emitSourceFile(sourceFile) { currentSourceFile = sourceFile; + currentText = sourceFile.text; + currentLineMap = ts.getLineStarts(sourceFile); exportFunctionForFile = undefined; + isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; + renamedDependencies = sourceFile.renamedDependencies; + currentFileIdentifiers = sourceFile.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(sourceFile); emit(sourceFile); } function isUniqueName(name) { return !resolver.hasGlobalName(name) && - !ts.hasProperty(currentSourceFile.identifiers, name) && + !ts.hasProperty(currentFileIdentifiers, name) && !ts.hasProperty(generatedNameSet, name); } function makeTempVariableName(flags) { @@ -25431,7 +25815,7 @@ var ts; var id = ts.getNodeId(node); return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); } - function initializeEmitterWithSourceMaps() { + function initializeEmitterWithSourceMaps(jsFilePath, root) { var sourceMapDir; var sourceMapSourceIndex = -1; var sourceMapNameIndexMap = {}; @@ -25500,7 +25884,7 @@ var ts; } } function recordSourceMapSpan(pos) { - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + var sourceLinePos = ts.computeLineAndCharacterOfPosition(currentLineMap, pos); sourceLinePos.line++; sourceLinePos.character++; var emittedLine = writer.getLine(); @@ -25528,13 +25912,13 @@ var ts; } } function recordEmitNodeStartSpan(node) { - recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos)); + recordSourceMapSpan(ts.skipTrivia(currentText, node.pos)); } function recordEmitNodeEndSpan(node) { recordSourceMapSpan(node.end); } function writeTextWithSpanRecord(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos); + var tokenStartPos = ts.skipTrivia(currentText, startPos); recordSourceMapSpan(tokenStartPos); var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn); recordSourceMapSpan(tokenEndPos); @@ -25604,9 +25988,9 @@ var ts; sourceMapNameIndices.pop(); } ; - function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) { + function writeCommentRangeWithMap(currentText, currentLineMap, writer, comment, newLine) { recordSourceMapSpan(comment.pos); - ts.writeCommentRange(currentSourceFile, writer, comment, newLine); + ts.writeCommentRange(currentText, currentLineMap, writer, comment, newLine); recordSourceMapSpan(comment.end); } function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings, sourcesContent) { @@ -25636,7 +26020,7 @@ var ts; return output; } } - function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptAndSourceMapFile(emitOutput, jsFilePath, writeByteOrderMark) { encodeLastRecordedSourceMapSpan(); var sourceMapText = serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings, sourceMapData.sourceMapSourcesContent); sourceMapDataList.push(sourceMapData); @@ -25649,7 +26033,7 @@ var ts; ts.writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, sourceMapText, false); sourceMapUrl = "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL; } - writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark); + writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark); } var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath)); sourceMapData = { @@ -25712,7 +26096,7 @@ var ts; scopeEmitEnd = recordScopeNameEnd; writeComment = writeCommentRangeWithMap; } - function writeJavaScriptFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptFile(emitOutput, jsFilePath, writeByteOrderMark) { ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark); } function createTempVariable(flags) { @@ -25882,7 +26266,7 @@ var ts; return getQuotedEscapedLiteralText("\"", node.text, "\""); } if (node.parent) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + return ts.getTextOfNodeFromSourceText(currentText, node); } switch (node.kind) { case 9: @@ -25904,7 +26288,7 @@ var ts; return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote; } function emitDownlevelRawTemplateLiteral(node) { - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + var text = ts.getTextOfNodeFromSourceText(currentText, node); var isLast = node.kind === 11 || node.kind === 14; text = text.substring(1, text.length - (isLast ? 1 : 2)); text = text.replace(/\r\n?/g, "\n"); @@ -26234,7 +26618,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } write("\""); } @@ -26330,7 +26714,7 @@ var ts; else if (declaration.kind === 226) { write(getGeneratedNameForNode(declaration.parent.parent.parent)); var name_24 = declaration.propertyName || declaration.name; - var identifier = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, name_24); + var identifier = ts.getTextOfNodeFromSourceText(currentText, name_24); if (languageVersion === 0 && identifier === "default") { write("[\"default\"]"); } @@ -26354,7 +26738,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function isNameOfNestedRedeclaration(node) { @@ -26391,7 +26775,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function emitThis(node) { @@ -26758,8 +27142,8 @@ var ts; return container && container.kind !== 248; } function emitShorthandPropertyAssignment(node) { - writeTextOfNode(currentSourceFile, node.name); - if (languageVersion < 2 || isNamespaceExportReference(node.name)) { + writeTextOfNode(currentText, node.name); + if (modulekind !== 5 || isNamespaceExportReference(node.name)) { write(": "); emit(node.name); } @@ -26809,10 +27193,10 @@ var ts; } emit(node.expression); var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); - var shouldEmitSpace; + var shouldEmitSpace = false; if (!indentedBeforeDot) { if (node.expression.kind === 8) { - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression); + var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); shouldEmitSpace = text.indexOf(ts.tokenToString(21)) < 0; } else { @@ -27818,16 +28202,16 @@ var ts; emitToken(16, node.clauses.end); } function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, node2.end); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); } function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function emitCaseOrDefaultClause(node) { if (node.kind === 241) { @@ -27932,7 +28316,7 @@ var ts; if (node.parent.kind === 248) { ts.Debug.assert(!!(node.flags & 512) || node.kind === 227); if (modulekind === 1 || modulekind === 2 || modulekind === 3) { - if (!currentSourceFile.symbol.exports["___esModule"]) { + if (!isEs6Module) { if (languageVersion === 1) { write("Object.defineProperty(exports, \"__esModule\", { value: true });"); writeLine(); @@ -28095,12 +28479,18 @@ var ts; return node; } function createPropertyAccessForDestructuringProperty(object, propName) { - var syntheticName = ts.createSynthesizedNode(propName.kind); - syntheticName.text = propName.text; - if (syntheticName.kind !== 69) { - return createElementAccessExpression(object, syntheticName); + var index; + var nameIsComputed = propName.kind === 136; + if (nameIsComputed) { + index = ensureIdentifier(propName.expression, false); } - return createPropertyAccessExpression(object, syntheticName); + else { + index = ts.createSynthesizedNode(propName.kind); + index.text = propName.text; + } + return !nameIsComputed && index.kind === 69 + ? createPropertyAccessExpression(object, index) + : createElementAccessExpression(object, index); } function createSliceCall(value, sliceIndex) { var call = ts.createSynthesizedNode(168); @@ -28514,7 +28904,6 @@ var ts; var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); var isArrowFunction = node.kind === 174; var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 4096) !== 0; - var args; if (!isArrowFunction) { write(" {"); increaseIndent(); @@ -29688,8 +30077,8 @@ var ts; } } function tryRenameExternalModule(moduleName) { - if (currentSourceFile.renamedDependencies && ts.hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) { - return "\"" + currentSourceFile.renamedDependencies[moduleName.text] + "\""; + if (renamedDependencies && ts.hasProperty(renamedDependencies, moduleName.text)) { + return "\"" + renamedDependencies[moduleName.text] + "\""; } return undefined; } @@ -29829,7 +30218,7 @@ var ts; return; } if (resolver.isReferencedAliasDeclaration(node) || - (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { + (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { emitLeadingComments(node); emitStart(node); var variableDeclarationIsHoisted = shouldHoistVariable(node, true); @@ -30041,7 +30430,7 @@ var ts; function getLocalNameForExternalImport(node) { var namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); + return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); } if (node.kind === 222 && node.importClause) { return getGeneratedNameForNode(node); @@ -30314,7 +30703,7 @@ var ts; ts.getEnclosingBlockScopeContainer(node).kind === 248; } function isCurrentFileSystemExternalModule() { - return modulekind === 4 && ts.isExternalModule(currentSourceFile); + return modulekind === 4 && isCurrentFileExternalModule; } function emitSystemModuleBody(node, dependencyGroups, startIndex) { emitVariableDeclarationsForImports(); @@ -30427,15 +30816,19 @@ var ts; writeLine(); write("}"); } - function emitSystemModule(node) { + function writeModuleName(node, emitRelativePathAsModuleName) { + var moduleName = node.moduleName; + if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { + write("\"" + moduleName + "\", "); + } + } + function emitSystemModule(node, emitRelativePathAsModuleName) { collectExternalModuleInfo(node); ts.Debug.assert(!exportFunctionForFile); exportFunctionForFile = makeUniqueName("exports"); writeLine(); write("System.register("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } + writeModuleName(node, emitRelativePathAsModuleName); write("["); var groupIndices = {}; var dependencyGroups = []; @@ -30453,6 +30846,12 @@ var ts; if (i !== 0) { write(", "); } + if (emitRelativePathAsModuleName) { + var name_30 = getExternalModuleNameFromDeclaration(host, resolver, externalImports[i]); + if (name_30) { + text = "\"" + name_30 + "\""; + } + } write(text); } write("], function(" + exportFunctionForFile + ") {"); @@ -30466,7 +30865,7 @@ var ts; writeLine(); write("});"); } - function getAMDDependencyNames(node, includeNonAmdDependencies) { + function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { var aliasedModuleNames = []; var unaliasedModuleNames = []; var importAliasNames = []; @@ -30483,6 +30882,12 @@ var ts; for (var _c = 0, externalImports_4 = externalImports; _c < externalImports_4.length; _c++) { var importNode = externalImports_4[_c]; var externalModuleName = getExternalModuleNameText(importNode); + if (emitRelativePathAsModuleName) { + var name_31 = getExternalModuleNameFromDeclaration(host, resolver, importNode); + if (name_31) { + externalModuleName = "\"" + name_31 + "\""; + } + } var importAliasName = getLocalNameForExternalImport(importNode); if (includeNonAmdDependencies && importAliasName) { aliasedModuleNames.push(externalModuleName); @@ -30494,8 +30899,8 @@ var ts; } return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies) { - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies); + function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { + var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); emitAMDDependencyList(dependencyNames); write(", "); emitAMDFactoryHeader(dependencyNames); @@ -30522,15 +30927,13 @@ var ts; } write(") {"); } - function emitAMDModule(node) { + function emitAMDModule(node, emitRelativePathAsModuleName) { emitEmitHelpers(node); collectExternalModuleInfo(node); writeLine(); write("define("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } - emitAMDDependencies(node, true); + writeModuleName(node, emitRelativePathAsModuleName); + emitAMDDependencies(node, true, emitRelativePathAsModuleName); increaseIndent(); var startIndex = emitDirectivePrologues(node.statements, true); emitExportStarHelper(); @@ -30736,8 +31139,13 @@ var ts; emitShebang(); emitDetachedCommentsAndUpdateCommentsInfo(node); if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1]; - emitModule(node); + if (root || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { + var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1]; + emitModule(node); + } + else { + bundleEmitDelegates[modulekind](node, true); + } } else { var startIndex = emitDirectivePrologues(node.statements, false); @@ -30981,7 +31389,7 @@ var ts; return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; } function getLeadingCommentsWithoutDetachedComments() { - var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); + var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); } @@ -30991,10 +31399,10 @@ var ts; return leadingComments; } function isTripleSlashComment(comment) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 && + if (currentText.charCodeAt(comment.pos + 1) === 47 && comment.pos + 2 < comment.end && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 47) { - var textSubStr = currentSourceFile.text.substring(comment.pos, comment.end); + currentText.charCodeAt(comment.pos + 2) === 47) { + var textSubStr = currentText.substring(comment.pos, comment.end); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? true : false; @@ -31008,7 +31416,7 @@ var ts; return getLeadingCommentsWithoutDetachedComments(); } else { - return ts.getLeadingCommentRangesOfNode(node, currentSourceFile); + return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); } } } @@ -31016,7 +31424,7 @@ var ts; function getTrailingCommentsToEmit(node) { if (node.parent) { if (node.parent.kind === 248 || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentSourceFile.text, node.end); + return ts.getTrailingCommentRanges(currentText, node.end); } } } @@ -31039,22 +31447,22 @@ var ts; leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); } } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, true, newLine, writeComment); } function emitTrailingComments(node) { if (compilerOptions.removeComments) { return; } var trailingComments = getTrailingCommentsToEmit(node); - ts.emitComments(currentSourceFile, writer, trailingComments, false, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, false, newLine, writeComment); } function emitTrailingCommentsOfPosition(pos) { if (compilerOptions.removeComments) { return; } - var trailingComments = ts.getTrailingCommentRanges(currentSourceFile.text, pos); - ts.emitComments(currentSourceFile, writer, trailingComments, true, newLine, writeComment); + var trailingComments = ts.getTrailingCommentRanges(currentText, pos); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, true, newLine, writeComment); } function emitLeadingCommentsOfPositionWorker(pos) { if (compilerOptions.removeComments) { @@ -31065,13 +31473,13 @@ var ts; leadingComments = getLeadingCommentsWithoutDetachedComments(); } else { - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos); + leadingComments = ts.getLeadingCommentRanges(currentText, pos); } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments); - ts.emitComments(currentSourceFile, writer, leadingComments, true, newLine, writeComment); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, true, newLine, writeComment); } function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments); + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -31082,12 +31490,12 @@ var ts; } } function emitShebang() { - var shebang = ts.getShebang(currentSourceFile.text); + var shebang = ts.getShebang(currentText); if (shebang) { write(shebang); } } - var _a; + var _a, _b; } function emitFile(jsFilePath, sourceFile) { emitJavaScript(jsFilePath, sourceFile); @@ -31143,11 +31551,11 @@ var ts; if (ts.getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { var failedLookupLocations = []; var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var resolvedFileName = loadNodeModuleFromFile(ts.supportedJsExtensions, candidate, failedLookupLocations, host); if (resolvedFileName) { return { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations }; } - resolvedFileName = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + resolvedFileName = loadNodeModuleFromDirectory(ts.supportedJsExtensions, candidate, failedLookupLocations, host); return resolvedFileName ? { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations } : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; @@ -31157,8 +31565,8 @@ var ts; } } ts.nodeModuleNameResolver = nodeModuleNameResolver; - function loadNodeModuleFromFile(candidate, failedLookupLocation, host) { - return ts.forEach(ts.moduleFileExtensions, tryLoad); + function loadNodeModuleFromFile(extensions, candidate, failedLookupLocation, host) { + return ts.forEach(extensions, tryLoad); function tryLoad(ext) { var fileName = ts.fileExtensionIs(candidate, ext) ? candidate : candidate + ext; if (host.fileExists(fileName)) { @@ -31170,7 +31578,7 @@ var ts; } } } - function loadNodeModuleFromDirectory(candidate, failedLookupLocation, host) { + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, host) { var packageJsonPath = ts.combinePaths(candidate, "package.json"); if (host.fileExists(packageJsonPath)) { var jsonContent; @@ -31182,7 +31590,7 @@ var ts; jsonContent = { typings: undefined }; } if (jsonContent.typings) { - var result = loadNodeModuleFromFile(ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); + var result = loadNodeModuleFromFile(extensions, ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); if (result) { return result; } @@ -31191,7 +31599,7 @@ var ts; else { failedLookupLocation.push(packageJsonPath); } - return loadNodeModuleFromFile(ts.combinePaths(candidate, "index"), failedLookupLocation, host); + return loadNodeModuleFromFile(extensions, ts.combinePaths(candidate, "index"), failedLookupLocation, host); } function loadModuleFromNodeModules(moduleName, directory, host) { var failedLookupLocations = []; @@ -31201,11 +31609,11 @@ var ts; if (baseName !== "node_modules") { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var result = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var result = loadNodeModuleFromFile(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } - result = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + result = loadNodeModuleFromDirectory(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } @@ -31230,9 +31638,10 @@ var ts; var searchName; var failedLookupLocations = []; var referencedSourceFile; + var extensions = compilerOptions.allowNonTsExtensions ? ts.supportedJsExtensions : ts.supportedExtensions; while (true) { searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleName)); - referencedSourceFile = ts.forEach(ts.supportedExtensions, function (extension) { + referencedSourceFile = ts.forEach(extensions, function (extension) { if (extension === ".tsx" && !compilerOptions.jsx) { return undefined; } @@ -31260,10 +31669,8 @@ var ts; ts.classicNameResolver = classicNameResolver; ts.defaultInitCompilerOptions = { module: 1, - target: 0, + target: 1, noImplicitAny: false, - outDir: "built", - rootDir: ".", sourceMap: false }; function createCompilerHost(options, setParentNodes) { @@ -31621,35 +32028,47 @@ var ts; if (file.imports) { return; } + var isJavaScriptFile = ts.isSourceFileJavaScript(file); var imports; for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collect(node, true); + collect(node, true, false); } file.imports = imports || emptyArray; - function collect(node, allowRelativeModuleNames) { - switch (node.kind) { - case 222: - case 221: - case 228: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9) { + return; + function collect(node, allowRelativeModuleNames, collectOnlyRequireCalls) { + if (!collectOnlyRequireCalls) { + switch (node.kind) { + case 222: + case 221: + case 228: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9) { + break; + } + if (!moduleNameExpr.text) { + break; + } + if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); + } break; - } - if (!moduleNameExpr.text) { + case 218: + if (node.name.kind === 9 && (node.flags & 4 || ts.isDeclarationFile(file))) { + ts.forEachChild(node.body, function (node) { + collect(node, false, collectOnlyRequireCalls); + }); + } break; - } - if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 218: - if (node.name.kind === 9 && (node.flags & 4 || ts.isDeclarationFile(file))) { - ts.forEachChild(node.body, function (node) { - collect(node, false); - }); - } - break; + } + } + if (isJavaScriptFile) { + if (ts.isRequireCall(node)) { + (imports || (imports = [])).push(node.arguments[0]); + } + else { + ts.forEachChild(node, function (node) { return collect(node, allowRelativeModuleNames, true); }); + } } } } @@ -31736,7 +32155,6 @@ var ts; } processImportedModules(file, basePath); if (isDefaultLib) { - file.isDefaultLib = true; files.unshift(file); } else { @@ -31809,6 +32227,9 @@ var ts; commonPathComponents.length = sourcePathComponents.length; } }); + if (!commonPathComponents) { + return currentDirectory; + } return ts.getNormalizedPathFromPathComponents(commonPathComponents); } function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { @@ -31891,10 +32312,12 @@ var ts; if (options.module === 5 && languageVersion < 2) { programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower)); } + if (outFile && options.module && !(options.module === 2 || options.module === 4)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } if (options.outDir || options.sourceRoot || - (options.mapRoot && - (!outFile || firstExternalModuleSourceFile !== undefined))) { + options.mapRoot) { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); } @@ -32448,10 +32871,10 @@ var ts; ts.forEach(program.getSourceFiles(), function (sourceFile) { cancellationToken.throwIfCancellationRequested(); var nameToDeclarations = sourceFile.getNamedDeclarations(); - for (var name_30 in nameToDeclarations) { - var declarations = ts.getProperty(nameToDeclarations, name_30); + for (var name_32 in nameToDeclarations) { + var declarations = ts.getProperty(nameToDeclarations, name_32); if (declarations) { - var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_30); + var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_32); if (!matches) { continue; } @@ -32462,14 +32885,14 @@ var ts; if (!containers) { return undefined; } - matches = patternMatcher.getMatches(containers, name_30); + matches = patternMatcher.getMatches(containers, name_32); if (!matches) { continue; } } var fileName = sourceFile.fileName; var matchKind = bestMatchKind(matches); - rawItems.push({ name: name_30, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); + rawItems.push({ name: name_32, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); } } } @@ -32797,9 +33220,9 @@ var ts; case 211: case 163: var variableDeclarationNode; - var name_31; + var name_33; if (node.kind === 163) { - name_31 = node.name; + name_33 = node.name; variableDeclarationNode = node; while (variableDeclarationNode && variableDeclarationNode.kind !== 211) { variableDeclarationNode = variableDeclarationNode.parent; @@ -32809,16 +33232,16 @@ var ts; else { ts.Debug.assert(!ts.isBindingPattern(node.name)); variableDeclarationNode = node; - name_31 = node.name; + name_33 = node.name; } if (ts.isConst(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.constElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.constElement); } else if (ts.isLet(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.letElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.letElement); } else { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.variableElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.variableElement); } case 144: return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement); @@ -33425,7 +33848,7 @@ var ts; var resolvedSignature = typeChecker.getResolvedSignature(call, candidates); cancellationToken.throwIfCancellationRequested(); if (!candidates.length) { - if (ts.isJavaScript(sourceFile.fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { return createJavaScriptSignatureHelpItems(argumentInfo); } return undefined; @@ -34941,9 +35364,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_32 in o) { - if (o[name_32] === rule) { - return name_32; + for (var name_34 in o) { + if (o[name_34] === rule) { + return name_34; } } throw new Error("Unknown rule"); @@ -35318,7 +35741,7 @@ var ts; function TokenRangeAccess(from, to, except) { this.tokens = []; for (var token = from; token <= to; token++) { - if (except.indexOf(token) < 0) { + if (ts.indexOf(except, token) < 0) { this.tokens.push(token); } } @@ -36706,13 +37129,18 @@ var ts; ]; var jsDocCompletionEntries; function createNode(kind, pos, end, flags, parent) { - var node = new (ts.getNodeConstructor(kind))(pos, end); + var node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; } var NodeObject = (function () { - function NodeObject() { + function NodeObject(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0; + this.parent = undefined; } NodeObject.prototype.getSourceFile = function () { return ts.getSourceFileOfNode(this); @@ -37151,8 +37579,8 @@ var ts; })(); var SourceFileObject = (function (_super) { __extends(SourceFileObject, _super); - function SourceFileObject() { - _super.apply(this, arguments); + function SourceFileObject(kind, pos, end) { + _super.call(this, kind, pos, end); } SourceFileObject.prototype.update = function (newText, textChangeRange) { return ts.updateSourceFile(this, newText, textChangeRange); @@ -37421,6 +37849,9 @@ var ts; ClassificationTypeNames.typeAliasName = "type alias name"; ClassificationTypeNames.parameterName = "parameter name"; ClassificationTypeNames.docCommentTagName = "doc comment tag name"; + ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; + ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; + ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; @@ -37740,8 +38171,9 @@ var ts; }; } ts.createDocumentRegistry = createDocumentRegistry; - function preProcessFile(sourceText, readImportFiles) { + function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) { if (readImportFiles === void 0) { readImportFiles = true; } + if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } var referencedFiles = []; var importedFiles = []; var ambientExternalModules; @@ -37775,93 +38207,53 @@ var ts; end: pos + importPath.length }); } - function processImport() { - scanner.setText(sourceText); - var token = scanner.scan(); - while (token !== 1) { - if (token === 122) { - token = scanner.scan(); - if (token === 125) { - token = scanner.scan(); - if (token === 9) { - recordAmbientExternalModule(); - continue; - } - } - } - else if (token === 89) { + function tryConsumeDeclare() { + var token = scanner.getToken(); + if (token === 122) { + token = scanner.scan(); + if (token === 125) { token = scanner.scan(); if (token === 9) { - recordModuleName(); - continue; - } - else { - if (token === 69 || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133) { - token = scanner.scan(); - if (token === 9) { - recordModuleName(); - continue; - } - } - else if (token === 56) { - token = scanner.scan(); - if (token === 127) { - token = scanner.scan(); - if (token === 17) { - token = scanner.scan(); - if (token === 9) { - recordModuleName(); - continue; - } - } - } - } - else if (token === 24) { - token = scanner.scan(); - } - else { - continue; - } - } - if (token === 15) { - token = scanner.scan(); - while (token !== 16) { - token = scanner.scan(); - } - if (token === 16) { - token = scanner.scan(); - if (token === 133) { - token = scanner.scan(); - if (token === 9) { - recordModuleName(); - } - } - } - } - else if (token === 37) { - token = scanner.scan(); - if (token === 116) { - token = scanner.scan(); - if (token === 69 || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133) { - token = scanner.scan(); - if (token === 9) { - recordModuleName(); - } - } - } - } - } + recordAmbientExternalModule(); } } - else if (token === 82) { - token = scanner.scan(); + return true; + } + return false; + } + function tryConsumeImport() { + var token = scanner.getToken(); + if (token === 89) { + token = scanner.scan(); + if (token === 9) { + recordModuleName(); + return true; + } + else { + if (token === 69 || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133) { + token = scanner.scan(); + if (token === 9) { + recordModuleName(); + return true; + } + } + else if (token === 56) { + if (tryConsumeRequireCall(true)) { + return true; + } + } + else if (token === 24) { + token = scanner.scan(); + } + else { + return true; + } + } if (token === 15) { token = scanner.scan(); - while (token !== 16) { + while (token !== 16 && token !== 1) { token = scanner.scan(); } if (token === 16) { @@ -37875,6 +38267,35 @@ var ts; } } else if (token === 37) { + token = scanner.scan(); + if (token === 116) { + token = scanner.scan(); + if (token === 69 || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133) { + token = scanner.scan(); + if (token === 9) { + recordModuleName(); + } + } + } + } + } + } + return true; + } + return false; + } + function tryConsumeExport() { + var token = scanner.getToken(); + if (token === 82) { + token = scanner.scan(); + if (token === 15) { + token = scanner.scan(); + while (token !== 16 && token !== 1) { + token = scanner.scan(); + } + if (token === 16) { token = scanner.scan(); if (token === 133) { token = scanner.scan(); @@ -37883,31 +38304,99 @@ var ts; } } } - else if (token === 89) { + } + else if (token === 37) { + token = scanner.scan(); + if (token === 133) { token = scanner.scan(); - if (token === 69 || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 56) { - token = scanner.scan(); - if (token === 127) { - token = scanner.scan(); - if (token === 17) { - token = scanner.scan(); - if (token === 9) { - recordModuleName(); - } - } - } + if (token === 9) { + recordModuleName(); + } + } + } + else if (token === 89) { + token = scanner.scan(); + if (token === 69 || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 56) { + if (tryConsumeRequireCall(true)) { + return true; } } } } + return true; + } + return false; + } + function tryConsumeRequireCall(skipCurrentToken) { + var token = skipCurrentToken ? scanner.scan() : scanner.getToken(); + if (token === 127) { token = scanner.scan(); + if (token === 17) { + token = scanner.scan(); + if (token === 9) { + recordModuleName(); + } + } + return true; + } + return false; + } + function tryConsumeDefine() { + var token = scanner.getToken(); + if (token === 69 && scanner.getTokenValue() === "define") { + token = scanner.scan(); + if (token !== 17) { + return true; + } + token = scanner.scan(); + if (token === 9) { + token = scanner.scan(); + if (token === 24) { + token = scanner.scan(); + } + else { + return true; + } + } + if (token !== 19) { + return true; + } + token = scanner.scan(); + var i = 0; + while (token !== 20 && token !== 1) { + if (token === 9) { + recordModuleName(); + i++; + } + token = scanner.scan(); + } + return true; + } + return false; + } + function processImports() { + scanner.setText(sourceText); + scanner.scan(); + while (true) { + if (scanner.getToken() === 1) { + break; + } + if (tryConsumeDeclare() || + tryConsumeImport() || + tryConsumeExport() || + (detectJavaScriptImports && (tryConsumeRequireCall(false) || tryConsumeDefine()))) { + continue; + } + else { + scanner.scan(); + } } scanner.setText(undefined); } if (readImportFiles) { - processImport(); + processImports(); } processTripleSlashDirectives(); return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientExternalModules }; @@ -38250,7 +38739,7 @@ var ts; function getSemanticDiagnostics(fileName) { synchronizeHostData(); var targetSourceFile = getValidSourceFile(fileName); - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(targetSourceFile)) { return getJavaScriptSemanticDiagnostics(targetSourceFile); } var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); @@ -38442,7 +38931,7 @@ var ts; var typeChecker = program.getTypeChecker(); var syntacticStart = new Date().getTime(); var sourceFile = getValidSourceFile(fileName); - var isJavaScriptFile = ts.isJavaScript(fileName); + var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); var isJsDocTagName = false; var start = new Date().getTime(); var currentToken = ts.getTokenAtPosition(sourceFile, position); @@ -38953,8 +39442,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_33 = element.propertyName || element.name; - exisingImportsOrExports[name_33.text] = true; + var name_35 = element.propertyName || element.name; + exisingImportsOrExports[name_35.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -38978,7 +39467,9 @@ var ts; } var existingName = void 0; if (m.kind === 163 && m.propertyName) { - existingName = m.propertyName.text; + if (m.propertyName.kind === 69) { + existingName = m.propertyName.text; + } } else { existingName = m.name.text; @@ -39008,44 +39499,41 @@ var ts; return undefined; } var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isRightOfDot = completionData.isRightOfDot, isJsDocTagName = completionData.isJsDocTagName; - var entries; if (isJsDocTagName) { return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - if (isRightOfDot && ts.isJavaScript(fileName)) { - entries = getCompletionEntriesFromSymbols(symbols); - ts.addRange(entries, getJavaScriptCompletionEntries()); + var sourceFile = getValidSourceFile(fileName); + var entries = []; + if (isRightOfDot && ts.isSourceFileJavaScript(sourceFile)) { + var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); + ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, uniqueNames)); } else { if (!symbols || symbols.length === 0) { return undefined; } - entries = getCompletionEntriesFromSymbols(symbols); + getCompletionEntriesFromSymbols(symbols, entries); } if (!isMemberCompletion && !isJsDocTagName) { ts.addRange(entries, keywordCompletions); } return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries }; - function getJavaScriptCompletionEntries() { + function getJavaScriptCompletionEntries(sourceFile, uniqueNames) { var entries = []; - var allNames = {}; var target = program.getCompilerOptions().target; - for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { - var sourceFile = _a[_i]; - var nameTable = getNameTable(sourceFile); - for (var name_34 in nameTable) { - if (!allNames[name_34]) { - allNames[name_34] = name_34; - var displayName = getCompletionEntryDisplayName(name_34, target, true); - if (displayName) { - var entry = { - name: displayName, - kind: ScriptElementKind.warning, - kindModifiers: "", - sortText: "1" - }; - entries.push(entry); - } + var nameTable = getNameTable(sourceFile); + for (var name_36 in nameTable) { + if (!uniqueNames[name_36]) { + uniqueNames[name_36] = name_36; + var displayName = getCompletionEntryDisplayName(name_36, target, true); + if (displayName) { + var entry = { + name: displayName, + kind: ScriptElementKind.warning, + kindModifiers: "", + sortText: "1" + }; + entries.push(entry); } } } @@ -39073,25 +39561,24 @@ var ts; sortText: "0" }; } - function getCompletionEntriesFromSymbols(symbols) { + function getCompletionEntriesFromSymbols(symbols, entries) { var start = new Date().getTime(); - var entries = []; + var uniqueNames = {}; if (symbols) { - var nameToSymbol = {}; for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) { var symbol = symbols_3[_i]; var entry = createCompletionEntry(symbol, location); if (entry) { var id = ts.escapeIdentifier(entry.name); - if (!ts.lookUp(nameToSymbol, id)) { + if (!ts.lookUp(uniqueNames, id)) { entries.push(entry); - nameToSymbol[id] = symbol; + uniqueNames[id] = id; } } } } log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start)); - return entries; + return uniqueNames; } } function getCompletionEntryDetails(fileName, position, entryName) { @@ -39272,16 +39759,16 @@ var ts; case ScriptElementKind.letElement: case ScriptElementKind.parameterElement: case ScriptElementKind.localVariableElement: - displayParts.push(ts.punctuationPart(54)); + displayParts.push(ts.punctuationPart(ts.SyntaxKind.ColonToken)); displayParts.push(ts.spacePart()); if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92)); + displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); displayParts.push(ts.spacePart()); } - if (!(type.flags & 65536)) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, 1)); + if (!(type.flags & ts.TypeFlags.Anonymous)) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, ts.SymbolFormatFlags.WriteTypeParametersOrArguments)); } - addSignatureDisplayParts(signature, allSignatures, 8); + addSignatureDisplayParts(signature, allSignatures, ts.TypeFormatFlags.WriteArrowStyleSignature); break; default: addSignatureDisplayParts(signature, allSignatures); @@ -40728,17 +41215,17 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_35 = node.text; + var name_37 = node.text; if (contextualType) { if (contextualType.flags & 16384) { - var unionProperty = contextualType.getProperty(name_35); + var unionProperty = contextualType.getProperty(name_37); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_35); + var symbol = t.getProperty(name_37); if (symbol) { result_4.push(symbol); } @@ -40747,7 +41234,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_35); + var symbol_1 = contextualType.getProperty(name_37); if (symbol_1) { return [symbol_1]; } @@ -41105,6 +41592,9 @@ var ts; case 16: return ClassificationTypeNames.typeAliasName; case 17: return ClassificationTypeNames.parameterName; case 18: return ClassificationTypeNames.docCommentTagName; + case 19: return ClassificationTypeNames.jsxOpenTagName; + case 20: return ClassificationTypeNames.jsxCloseTagName; + case 21: return ClassificationTypeNames.jsxSelfClosingTagName; } } function convertClassifications(classifications) { @@ -41344,6 +41834,21 @@ var ts; return 17; } return; + case 235: + if (token.parent.tagName === token) { + return 19; + } + return; + case 237: + if (token.parent.tagName === token) { + return 20; + } + return; + case 234: + if (token.parent.tagName === token) { + return 21; + } + return; } } return 2; @@ -42053,18 +42558,8 @@ var ts; ts.getDefaultLibFilePath = getDefaultLibFilePath; function initializeServices() { ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0; - this.parent = undefined; - } - var proto = kind === 248 ? new SourceFileObject() : new NodeObject(); - proto.kind = kind; - Node.prototype = proto; - return Node; - }, + getNodeConstructor: function () { return NodeObject; }, + getSourceFileConstructor: function () { return SourceFileObject; }, getSymbolConstructor: function () { return SymbolObject; }, getTypeConstructor: function () { return TypeObject; }, getSignatureConstructor: function () { return SignatureObject; } @@ -42959,8 +43454,8 @@ var ts; }; Session.prototype.getDiagnosticsForProject = function (delay, fileName) { var _this = this; - var _a = this.getProjectInfo(fileName, true), configFileName = _a.configFileName, fileNamesInProject = _a.fileNames; - fileNamesInProject = fileNamesInProject.filter(function (value, index, array) { return value.indexOf("lib.d.ts") < 0; }); + var _a = this.getProjectInfo(fileName, true), configFileName = _a.configFileName, fileNames = _a.fileNames; + var fileNamesInProject = fileNames.filter(function (value, index, array) { return value.indexOf("lib.d.ts") < 0; }); var highPriorityFiles = []; var mediumPriorityFiles = []; var lowPriorityFiles = []; @@ -43329,6 +43824,9 @@ var ts; this.filenameToSourceFile = {}; this.updateGraphSeq = 0; this.openRefCount = 0; + if (projectOptions && projectOptions.files) { + projectOptions.compilerOptions.allowNonTsExtensions = true; + } this.compilerService = new CompilerService(this, projectOptions && projectOptions.compilerOptions); } Project.prototype.addOpenRef = function () { @@ -43399,6 +43897,7 @@ var ts; Project.prototype.setProjectOptions = function (projectOptions) { this.projectOptions = projectOptions; if (projectOptions.compilerOptions) { + projectOptions.compilerOptions.allowNonTsExtensions = true; this.compilerService.setCompilerOptions(projectOptions.compilerOptions); } }; @@ -43824,7 +44323,6 @@ var ts; } } if (content !== undefined) { - var indentSize; info = new ScriptInfo(this.host, fileName, content, openedByClient); info.setFormatOptions(this.getFormatCodeOptions()); this.filenameToScriptInfo[fileName] = info; @@ -44081,7 +44579,9 @@ var ts; this.setCompilerOptions(opt); } else { - this.setCompilerOptions(ts.getDefaultCompilerOptions()); + var defaultOpts = ts.getDefaultCompilerOptions(); + defaultOpts.allowNonTsExtensions = true; + this.setCompilerOptions(defaultOpts); } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); this.classifier = ts.createClassifier(); @@ -45635,7 +46135,7 @@ var ts; }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { - var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength())); + var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), true, true); var convertResult = { referencedFiles: [], importedFiles: [], @@ -45696,7 +46196,7 @@ var ts; TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) { try { if (this.documentRegistry === undefined) { - this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry); @@ -45728,7 +46228,7 @@ var ts; }; TypeScriptServicesFactory.prototype.close = function () { this._shims = []; - this.documentRegistry = ts.createDocumentRegistry(); + this.documentRegistry = undefined; }; TypeScriptServicesFactory.prototype.registerShim = function (shim) { this._shims.push(shim); diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index 972ebfa472d..32a6dee4623 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -387,6 +387,7 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; + type PropertyName = Identifier | LiteralExpression | ComputedPropertyName; type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; @@ -425,7 +426,7 @@ declare namespace ts { initializer?: Expression; } interface BindingElement extends Declaration { - propertyName?: Identifier; + propertyName?: PropertyName; dotDotDotToken?: Node; name: Identifier | BindingPattern; initializer?: Expression; @@ -452,7 +453,7 @@ declare namespace ts { objectAssignmentInitializer?: Expression; } interface VariableLikeDeclaration extends Declaration { - propertyName?: Identifier; + propertyName?: PropertyName; dotDotDotToken?: Node; name: DeclarationName; questionToken?: Node; @@ -581,7 +582,7 @@ declare namespace ts { asteriskToken?: Node; expression?: Expression; } - interface BinaryExpression extends Expression { + interface BinaryExpression extends Expression, Declaration { left: Expression; operatorToken: Node; right: Expression; @@ -625,7 +626,7 @@ declare namespace ts { interface ObjectLiteralExpression extends PrimaryExpression, Declaration { properties: NodeArray; } - interface PropertyAccessExpression extends MemberExpression { + interface PropertyAccessExpression extends MemberExpression, Declaration { expression: LeftHandSideExpression; dotToken: Node; name: Identifier; @@ -1220,6 +1221,7 @@ declare namespace ts { ObjectLiteral = 524288, ESSymbol = 16777216, ThisType = 33554432, + ObjectLiteralPatternWithComputedProperties = 67108864, StringLike = 258, NumberLike = 132, ObjectType = 80896, @@ -1537,7 +1539,6 @@ declare namespace ts { function getTypeParameterOwner(d: Declaration): Declaration; } declare namespace ts { - function getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node; function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile; @@ -2126,6 +2127,9 @@ declare namespace ts { static typeAliasName: string; static parameterName: string; static docCommentTagName: string; + static jsxOpenTagName: string; + static jsxCloseTagName: string; + static jsxSelfClosingTagName: string; } enum ClassificationType { comment = 1, @@ -2146,6 +2150,9 @@ declare namespace ts { typeAliasName = 16, parameterName = 17, docCommentTagName = 18, + jsxOpenTagName = 19, + jsxCloseTagName = 20, + jsxSelfClosingTagName = 21, } interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; @@ -2171,7 +2178,7 @@ declare namespace ts { function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string; function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; - function preProcessFile(sourceText: string, readImportFiles?: boolean): PreProcessedFileInfo; + function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService; function createClassifier(): Classifier; /** diff --git a/lib/typescript.js b/lib/typescript.js index 8b0ef04f96e..498ddc37860 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -622,6 +622,7 @@ var ts; TypeFlags[TypeFlags["ContainsAnyFunctionType"] = 8388608] = "ContainsAnyFunctionType"; TypeFlags[TypeFlags["ESSymbol"] = 16777216] = "ESSymbol"; TypeFlags[TypeFlags["ThisType"] = 33554432] = "ThisType"; + TypeFlags[TypeFlags["ObjectLiteralPatternWithComputedProperties"] = 67108864] = "ObjectLiteralPatternWithComputedProperties"; /* @internal */ TypeFlags[TypeFlags["Intrinsic"] = 16777343] = "Intrinsic"; /* @internal */ @@ -1530,12 +1531,7 @@ var ts; * List of supported extensions in order of file resolution precedence. */ ts.supportedExtensions = [".ts", ".tsx", ".d.ts"]; - /** - * List of extensions that will be used to look for external modules. - * This list is kept separate from supportedExtensions to for cases when we'll allow to include .js files in compilation, - * but still would like to load only TypeScript files as modules - */ - ts.moduleFileExtensions = ts.supportedExtensions; + ts.supportedJsExtensions = ts.supportedExtensions.concat(".js", ".jsx"); function isSupportedSourceFileName(fileName) { if (!fileName) { return false; @@ -1586,17 +1582,16 @@ var ts; } function Signature(checker) { } + function Node(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; + } ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - } - Node.prototype = { kind: kind }; - return Node; - }, + getNodeConstructor: function () { return Node; }, + getSourceFileConstructor: function () { return Node; }, getSymbolConstructor: function () { return Symbol; }, getTypeConstructor: function () { return Type; }, getSignatureConstructor: function () { return Signature; } @@ -1913,7 +1908,16 @@ var ts; if (writeByteOrderMark) { data = "\uFEFF" + data; } - _fs.writeFileSync(fileName, data, "utf8"); + var fd; + try { + fd = _fs.openSync(fileName, "w"); + _fs.writeSync(fd, data, undefined, "utf8"); + } + finally { + if (fd !== undefined) { + _fs.closeSync(fd); + } + } } function getCanonicalPath(path) { return useCaseSensitiveFileNames ? path.toLowerCase() : path; @@ -2614,6 +2618,7 @@ var ts; Disallow_inconsistently_cased_references_to_the_same_file: { code: 6078, category: ts.DiagnosticCategory.Message, key: "Disallow_inconsistently_cased_references_to_the_same_file_6078", message: "Disallow inconsistently-cased references to the same file." }, Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: ts.DiagnosticCategory.Message, key: "Specify_JSX_code_generation_Colon_preserve_or_react_6080", message: "Specify JSX code generation: 'preserve' or 'react'" }, Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: ts.DiagnosticCategory.Message, key: "Argument_for_jsx_must_be_preserve_or_react_6081", message: "Argument for '--jsx' must be 'preserve' or 'react'." }, + Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -3173,7 +3178,7 @@ var ts; function getCommentRanges(text, pos, trailing) { var result; var collecting = trailing || pos === 0; - while (true) { + while (pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13 /* carriageReturn */: @@ -3242,6 +3247,7 @@ var ts; } return result; } + return result; } function getLeadingCommentRanges(text, pos) { return getCommentRanges(text, pos, /*trailing*/ false); @@ -3343,7 +3349,7 @@ var ts; error(ts.Diagnostics.Digit_expected); } } - return +(text.substring(start, end)); + return "" + +(text.substring(start, end)); } function scanOctalDigits() { var start = pos; @@ -3770,7 +3776,7 @@ var ts; return pos++, token = 36 /* MinusToken */; case 46 /* dot */: if (isDigit(text.charCodeAt(pos + 1))) { - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8 /* NumericLiteral */; } if (text.charCodeAt(pos + 1) === 46 /* dot */ && text.charCodeAt(pos + 2) === 46 /* dot */) { @@ -3873,7 +3879,7 @@ var ts; case 55 /* _7 */: case 56 /* _8 */: case 57 /* _9 */: - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8 /* NumericLiteral */; case 58 /* colon */: return pos++, token = 54 /* ColonToken */; @@ -4177,1321 +4183,6 @@ var ts; } ts.createScanner = createScanner; })(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - ts.bindTime = 0; - (function (ModuleInstanceState) { - ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; - ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; - ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; - })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); - var ModuleInstanceState = ts.ModuleInstanceState; - var Reachability; - (function (Reachability) { - Reachability[Reachability["Unintialized"] = 1] = "Unintialized"; - Reachability[Reachability["Reachable"] = 2] = "Reachable"; - Reachability[Reachability["Unreachable"] = 4] = "Unreachable"; - Reachability[Reachability["ReportedUnreachable"] = 8] = "ReportedUnreachable"; - })(Reachability || (Reachability = {})); - function or(state1, state2) { - return (state1 | state2) & 2 /* Reachable */ - ? 2 /* Reachable */ - : (state1 & state2) & 8 /* ReportedUnreachable */ - ? 8 /* ReportedUnreachable */ - : 4 /* Unreachable */; - } - function getModuleInstanceState(node) { - // A module is uninstantiated if it contains only - // 1. interface declarations, type alias declarations - if (node.kind === 215 /* InterfaceDeclaration */ || node.kind === 216 /* TypeAliasDeclaration */) { - return 0 /* NonInstantiated */; - } - else if (ts.isConstEnumDeclaration(node)) { - return 2 /* ConstEnumOnly */; - } - else if ((node.kind === 222 /* ImportDeclaration */ || node.kind === 221 /* ImportEqualsDeclaration */) && !(node.flags & 2 /* Export */)) { - return 0 /* NonInstantiated */; - } - else if (node.kind === 219 /* ModuleBlock */) { - var state = 0 /* NonInstantiated */; - ts.forEachChild(node, function (n) { - switch (getModuleInstanceState(n)) { - case 0 /* NonInstantiated */: - // child is non-instantiated - continue searching - return false; - case 2 /* ConstEnumOnly */: - // child is const enum only - record state and continue searching - state = 2 /* ConstEnumOnly */; - return false; - case 1 /* Instantiated */: - // child is instantiated - record state and stop - state = 1 /* Instantiated */; - return true; - } - }); - return state; - } - else if (node.kind === 218 /* ModuleDeclaration */) { - return getModuleInstanceState(node.body); - } - else { - return 1 /* Instantiated */; - } - } - ts.getModuleInstanceState = getModuleInstanceState; - var ContainerFlags; - (function (ContainerFlags) { - // The current node is not a container, and no container manipulation should happen before - // recursing into it. - ContainerFlags[ContainerFlags["None"] = 0] = "None"; - // The current node is a container. It should be set as the current container (and block- - // container) before recursing into it. The current node does not have locals. Examples: - // - // Classes, ObjectLiterals, TypeLiterals, Interfaces... - ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; - // The current node is a block-scoped-container. It should be set as the current block- - // container before recursing into it. Examples: - // - // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... - ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; - ContainerFlags[ContainerFlags["HasLocals"] = 4] = "HasLocals"; - // If the current node is a container that also container that also contains locals. Examples: - // - // Functions, Methods, Modules, Source-files. - ContainerFlags[ContainerFlags["IsContainerWithLocals"] = 5] = "IsContainerWithLocals"; - })(ContainerFlags || (ContainerFlags = {})); - var binder = createBinder(); - function bindSourceFile(file, options) { - var start = new Date().getTime(); - binder(file, options); - ts.bindTime += new Date().getTime() - start; - } - ts.bindSourceFile = bindSourceFile; - function createBinder() { - var file; - var options; - var parent; - var container; - var blockScopeContainer; - var lastContainer; - var seenThisKeyword; - // state used by reachability checks - var hasExplicitReturn; - var currentReachabilityState; - var labelStack; - var labelIndexMap; - var implicitLabels; - // If this file is an external module, then it is automatically in strict-mode according to - // ES6. If it is not an external module, then we'll determine if it is in strict mode or - // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). - var inStrictMode; - var symbolCount = 0; - var Symbol; - var classifiableNames; - function bindSourceFile(f, opts) { - file = f; - options = opts; - inStrictMode = !!file.externalModuleIndicator; - classifiableNames = {}; - Symbol = ts.objectAllocator.getSymbolConstructor(); - if (!file.locals) { - bind(file); - file.symbolCount = symbolCount; - file.classifiableNames = classifiableNames; - } - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - seenThisKeyword = false; - hasExplicitReturn = false; - labelStack = undefined; - labelIndexMap = undefined; - implicitLabels = undefined; - } - return bindSourceFile; - function createSymbol(flags, name) { - symbolCount++; - return new Symbol(flags, name); - } - function addDeclarationToSymbol(symbol, node, symbolFlags) { - symbol.flags |= symbolFlags; - node.symbol = symbol; - if (!symbol.declarations) { - symbol.declarations = []; - } - symbol.declarations.push(node); - if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { - symbol.exports = {}; - } - if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { - symbol.members = {}; - } - if (symbolFlags & 107455 /* Value */ && !symbol.valueDeclaration) { - symbol.valueDeclaration = node; - } - } - // Should not be called on a declaration with a computed property name, - // unless it is a well known Symbol. - function getDeclarationName(node) { - if (node.name) { - if (node.kind === 218 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */) { - return "\"" + node.name.text + "\""; - } - if (node.name.kind === 136 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); - return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); - } - return node.name.text; - } - switch (node.kind) { - case 144 /* Constructor */: - return "__constructor"; - case 152 /* FunctionType */: - case 147 /* CallSignature */: - return "__call"; - case 153 /* ConstructorType */: - case 148 /* ConstructSignature */: - return "__new"; - case 149 /* IndexSignature */: - return "__index"; - case 228 /* ExportDeclaration */: - return "__export"; - case 227 /* ExportAssignment */: - return node.isExportEquals ? "export=" : "default"; - case 213 /* FunctionDeclaration */: - case 214 /* ClassDeclaration */: - return node.flags & 512 /* Default */ ? "default" : undefined; - } - } - function getDisplayName(node) { - return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); - } - /** - * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. - * @param symbolTable - The symbol table which node will be added to. - * @param parent - node's parent declaration. - * @param node - The declaration to be added to the symbol table - * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) - * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. - */ - function declareSymbol(symbolTable, parent, node, includes, excludes) { - ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = node.flags & 512 /* Default */; - // The exported symbol for an export default function/class node is always named "default" - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); - var symbol; - if (name !== undefined) { - // Check and see if the symbol table already has a symbol with this name. If not, - // create a new symbol with this name and add it to the table. Note that we don't - // give the new symbol any flags *yet*. This ensures that it will not conflict - // with the 'excludes' flags we pass in. - // - // If we do get an existing symbol, see if it conflicts with the new symbol we're - // creating. For example, a 'var' symbol and a 'class' symbol will conflict within - // the same symbol table. If we have a conflict, report the issue on each - // declaration we have for this symbol, and then create a new symbol for this - // declaration. - // - // If we created a new symbol, either because we didn't have a symbol with this name - // in the symbol table, or we conflicted with an existing symbol, then just add this - // node as the sole declaration of the new symbol. - // - // Otherwise, we'll be merging into a compatible existing symbol (for example when - // you have multiple 'vars' with the same name in the same container). In this case - // just add this node into the declarations list of the symbol. - symbol = ts.hasProperty(symbolTable, name) - ? symbolTable[name] - : (symbolTable[name] = createSymbol(0 /* None */, name)); - if (name && (includes & 788448 /* Classifiable */)) { - classifiableNames[name] = name; - } - if (symbol.flags & excludes) { - if (node.name) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration - // Report errors on previous encountered declarations - var message = symbol.flags & 2 /* BlockScopedVariable */ - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.flags & 512 /* Default */) { - message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); - ts.forEach(symbol.declarations, function (declaration) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); - }); - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); - symbol = createSymbol(0 /* None */, name); - } - } - else { - symbol = createSymbol(0 /* None */, "__missing"); - } - addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; - return symbol; - } - function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedNodeFlags(node) & 2 /* Export */; - if (symbolFlags & 8388608 /* Alias */) { - if (node.kind === 230 /* ExportSpecifier */ || (node.kind === 221 /* ImportEqualsDeclaration */ && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - else { - // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, - // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set - // on it. There are 2 main reasons: - // - // 1. We treat locals and exports of the same name as mutually exclusive within a container. - // That means the binder will issue a Duplicate Identifier error if you mix locals and exports - // with the same name in the same container. - // TODO: Make this a more specific error and decouple it from the exclusion logic. - // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, - // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way - // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. - if (hasExportModifier || container.flags & 131072 /* ExportContext */) { - var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | - (symbolFlags & 793056 /* Type */ ? 2097152 /* ExportType */ : 0) | - (symbolFlags & 1536 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - node.localSymbol = local; - return local; - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - } - // All container nodes are kept on a linked list in declaration order. This list is used by - // the getLocalNameOfContainer function in the type checker to validate that the local name - // used for a container is unique. - function bindChildren(node) { - // Before we recurse into a node's chilren, we first save the existing parent, container - // and block-container. Then after we pop out of processing the children, we restore - // these saved values. - var saveParent = parent; - var saveContainer = container; - var savedBlockScopeContainer = blockScopeContainer; - // This node will now be set as the parent of all of its children as we recurse into them. - parent = node; - // Depending on what kind of node this is, we may have to adjust the current container - // and block-container. If the current node is a container, then it is automatically - // considered the current block-container as well. Also, for containers that we know - // may contain locals, we proactively initialize the .locals field. We do this because - // it's highly likely that the .locals will be needed to place some child in (for example, - // a parameter, or variable declaration). - // - // However, we do not proactively create the .locals for block-containers because it's - // totally normal and common for block-containers to never actually have a block-scoped - // variable in them. We don't want to end up allocating an object for every 'block' we - // run into when most of them won't be necessary. - // - // Finally, if this is a block-container, then we clear out any existing .locals object - // it may contain within it. This happens in incremental scenarios. Because we can be - // reusing a node from a previous compilation, that node may have had 'locals' created - // for it. We must clear this so we don't accidently move any stale data forward from - // a previous compilation. - var containerFlags = getContainerFlags(node); - if (containerFlags & 1 /* IsContainer */) { - container = blockScopeContainer = node; - if (containerFlags & 4 /* HasLocals */) { - container.locals = {}; - } - addToContainerChain(container); - } - else if (containerFlags & 2 /* IsBlockScopedContainer */) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; - } - var savedReachabilityState; - var savedLabelStack; - var savedLabels; - var savedImplicitLabels; - var savedHasExplicitReturn; - var kind = node.kind; - var flags = node.flags; - // reset all reachability check related flags on node (for incremental scenarios) - flags &= ~1572864 /* ReachabilityCheckFlags */; - if (kind === 215 /* InterfaceDeclaration */) { - seenThisKeyword = false; - } - var saveState = kind === 248 /* SourceFile */ || kind === 219 /* ModuleBlock */ || ts.isFunctionLikeKind(kind); - if (saveState) { - savedReachabilityState = currentReachabilityState; - savedLabelStack = labelStack; - savedLabels = labelIndexMap; - savedImplicitLabels = implicitLabels; - savedHasExplicitReturn = hasExplicitReturn; - currentReachabilityState = 2 /* Reachable */; - hasExplicitReturn = false; - labelStack = labelIndexMap = implicitLabels = undefined; - } - bindReachableStatement(node); - if (currentReachabilityState === 2 /* Reachable */ && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { - flags |= 524288 /* HasImplicitReturn */; - if (hasExplicitReturn) { - flags |= 1048576 /* HasExplicitReturn */; - } - } - if (kind === 215 /* InterfaceDeclaration */) { - flags = seenThisKeyword ? flags | 262144 /* ContainsThis */ : flags & ~262144 /* ContainsThis */; - } - node.flags = flags; - if (saveState) { - hasExplicitReturn = savedHasExplicitReturn; - currentReachabilityState = savedReachabilityState; - labelStack = savedLabelStack; - labelIndexMap = savedLabels; - implicitLabels = savedImplicitLabels; - } - container = saveContainer; - parent = saveParent; - blockScopeContainer = savedBlockScopeContainer; - } - /** - * Returns true if node and its subnodes were successfully traversed. - * Returning false means that node was not examined and caller needs to dive into the node himself. - */ - function bindReachableStatement(node) { - if (checkUnreachable(node)) { - ts.forEachChild(node, bind); - return; - } - switch (node.kind) { - case 198 /* WhileStatement */: - bindWhileStatement(node); - break; - case 197 /* DoStatement */: - bindDoStatement(node); - break; - case 199 /* ForStatement */: - bindForStatement(node); - break; - case 200 /* ForInStatement */: - case 201 /* ForOfStatement */: - bindForInOrForOfStatement(node); - break; - case 196 /* IfStatement */: - bindIfStatement(node); - break; - case 204 /* ReturnStatement */: - case 208 /* ThrowStatement */: - bindReturnOrThrow(node); - break; - case 203 /* BreakStatement */: - case 202 /* ContinueStatement */: - bindBreakOrContinueStatement(node); - break; - case 209 /* TryStatement */: - bindTryStatement(node); - break; - case 206 /* SwitchStatement */: - bindSwitchStatement(node); - break; - case 220 /* CaseBlock */: - bindCaseBlock(node); - break; - case 207 /* LabeledStatement */: - bindLabeledStatement(node); - break; - default: - ts.forEachChild(node, bind); - break; - } - } - function bindWhileStatement(n) { - var preWhileState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - var postWhileState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - // bind expressions (don't affect reachability) - bind(n.expression); - currentReachabilityState = preWhileState; - var postWhileLabel = pushImplicitLabel(); - bind(n.statement); - popImplicitLabel(postWhileLabel, postWhileState); - } - function bindDoStatement(n) { - var preDoState = currentReachabilityState; - var postDoLabel = pushImplicitLabel(); - bind(n.statement); - var postDoState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : preDoState; - popImplicitLabel(postDoLabel, postDoState); - // bind expressions (don't affect reachability) - bind(n.expression); - } - function bindForStatement(n) { - var preForState = currentReachabilityState; - var postForLabel = pushImplicitLabel(); - // bind expressions (don't affect reachability) - bind(n.initializer); - bind(n.condition); - bind(n.incrementor); - bind(n.statement); - // for statement is considered infinite when it condition is either omitted or is true keyword - // - for(..;;..) - // - for(..;true;..) - var isInfiniteLoop = (!n.condition || n.condition.kind === 99 /* TrueKeyword */); - var postForState = isInfiniteLoop ? 4 /* Unreachable */ : preForState; - popImplicitLabel(postForLabel, postForState); - } - function bindForInOrForOfStatement(n) { - var preStatementState = currentReachabilityState; - var postStatementLabel = pushImplicitLabel(); - // bind expressions (don't affect reachability) - bind(n.initializer); - bind(n.expression); - bind(n.statement); - popImplicitLabel(postStatementLabel, preStatementState); - } - function bindIfStatement(n) { - // denotes reachability state when entering 'thenStatement' part of the if statement: - // i.e. if condition is false then thenStatement is unreachable - var ifTrueState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - // denotes reachability state when entering 'elseStatement': - // i.e. if condition is true then elseStatement is unreachable - var ifFalseState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - currentReachabilityState = ifTrueState; - // bind expression (don't affect reachability) - bind(n.expression); - bind(n.thenStatement); - if (n.elseStatement) { - var preElseState = currentReachabilityState; - currentReachabilityState = ifFalseState; - bind(n.elseStatement); - currentReachabilityState = or(currentReachabilityState, preElseState); - } - else { - currentReachabilityState = or(currentReachabilityState, ifFalseState); - } - } - function bindReturnOrThrow(n) { - // bind expression (don't affect reachability) - bind(n.expression); - if (n.kind === 204 /* ReturnStatement */) { - hasExplicitReturn = true; - } - currentReachabilityState = 4 /* Unreachable */; - } - function bindBreakOrContinueStatement(n) { - // call bind on label (don't affect reachability) - bind(n.label); - // for continue case touch label so it will be marked a used - var isValidJump = jumpToLabel(n.label, n.kind === 203 /* BreakStatement */ ? currentReachabilityState : 4 /* Unreachable */); - if (isValidJump) { - currentReachabilityState = 4 /* Unreachable */; - } - } - function bindTryStatement(n) { - // catch\finally blocks has the same reachability as try block - var preTryState = currentReachabilityState; - bind(n.tryBlock); - var postTryState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.catchClause); - var postCatchState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.finallyBlock); - // post catch/finally state is reachable if - // - post try state is reachable - control flow can fall out of try block - // - post catch state is reachable - control flow can fall out of catch block - currentReachabilityState = or(postTryState, postCatchState); - } - function bindSwitchStatement(n) { - var preSwitchState = currentReachabilityState; - var postSwitchLabel = pushImplicitLabel(); - // bind expression (don't affect reachability) - bind(n.expression); - bind(n.caseBlock); - var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242 /* DefaultClause */; }); - // post switch state is unreachable if switch is exaustive (has a default case ) and does not have fallthrough from the last case - var postSwitchState = hasDefault && currentReachabilityState !== 2 /* Reachable */ ? 4 /* Unreachable */ : preSwitchState; - popImplicitLabel(postSwitchLabel, postSwitchState); - } - function bindCaseBlock(n) { - var startState = currentReachabilityState; - for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { - var clause = _a[_i]; - currentReachabilityState = startState; - bind(clause); - if (clause.statements.length && currentReachabilityState === 2 /* Reachable */ && options.noFallthroughCasesInSwitch) { - errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); - } - } - } - function bindLabeledStatement(n) { - // call bind on label (don't affect reachability) - bind(n.label); - var ok = pushNamedLabel(n.label); - bind(n.statement); - if (ok) { - popNamedLabel(n.label, currentReachabilityState); - } - } - function getContainerFlags(node) { - switch (node.kind) { - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - case 215 /* InterfaceDeclaration */: - case 217 /* EnumDeclaration */: - case 155 /* TypeLiteral */: - case 165 /* ObjectLiteralExpression */: - return 1 /* IsContainer */; - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - case 213 /* FunctionDeclaration */: - case 144 /* Constructor */: - case 145 /* GetAccessor */: - case 146 /* SetAccessor */: - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - case 218 /* ModuleDeclaration */: - case 248 /* SourceFile */: - case 216 /* TypeAliasDeclaration */: - return 5 /* IsContainerWithLocals */; - case 244 /* CatchClause */: - case 199 /* ForStatement */: - case 200 /* ForInStatement */: - case 201 /* ForOfStatement */: - case 220 /* CaseBlock */: - return 2 /* IsBlockScopedContainer */; - case 192 /* Block */: - // do not treat blocks directly inside a function as a block-scoped-container. - // Locals that reside in this block should go to the function locals. Othewise 'x' - // would not appear to be a redeclaration of a block scoped local in the following - // example: - // - // function foo() { - // var x; - // let x; - // } - // - // If we placed 'var x' into the function locals and 'let x' into the locals of - // the block, then there would be no collision. - // - // By not creating a new block-scoped-container here, we ensure that both 'var x' - // and 'let x' go into the Function-container's locals, and we do get a collision - // conflict. - return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; - } - return 0 /* None */; - } - function addToContainerChain(next) { - if (lastContainer) { - lastContainer.nextContainer = next; - } - lastContainer = next; - } - function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { - // Just call this directly so that the return type of this function stays "void". - declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); - } - function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { - switch (container.kind) { - // Modules, source files, and classes need specialized handling for how their - // members are declared (for example, a member of a class will go into a specific - // symbol table depending on if it is static or not). We defer to specialized - // handlers to take care of declaring these child members. - case 218 /* ModuleDeclaration */: - return declareModuleMember(node, symbolFlags, symbolExcludes); - case 248 /* SourceFile */: - return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - return declareClassMember(node, symbolFlags, symbolExcludes); - case 217 /* EnumDeclaration */: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 155 /* TypeLiteral */: - case 165 /* ObjectLiteralExpression */: - case 215 /* InterfaceDeclaration */: - // Interface/Object-types always have their children added to the 'members' of - // their container. They are only accessible through an instance of their - // container, and are never in scope otherwise (even inside the body of the - // object / type / interface declaring them). An exception is type parameters, - // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - case 144 /* Constructor */: - case 145 /* GetAccessor */: - case 146 /* SetAccessor */: - case 213 /* FunctionDeclaration */: - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - case 216 /* TypeAliasDeclaration */: - // All the children of these container types are never visible through another - // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, - // they're only accessed 'lexically' (i.e. from code that exists underneath - // their container in the tree. To accomplish this, we simply add their declared - // symbol to the 'locals' of the container. These symbols can then be found as - // the type checker walks up the containers, checking them for matching names. - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function declareClassMember(node, symbolFlags, symbolExcludes) { - return node.flags & 64 /* Static */ - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - } - function declareSourceFileMember(node, symbolFlags, symbolExcludes) { - return ts.isExternalModule(file) - ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); - } - function hasExportDeclarations(node) { - var body = node.kind === 248 /* SourceFile */ ? node : node.body; - if (body.kind === 248 /* SourceFile */ || body.kind === 219 /* ModuleBlock */) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var stat = _a[_i]; - if (stat.kind === 228 /* ExportDeclaration */ || stat.kind === 227 /* ExportAssignment */) { - return true; - } - } - } - return false; - } - function setExportContextFlag(node) { - // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular - // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { - node.flags |= 131072 /* ExportContext */; - } - else { - node.flags &= ~131072 /* ExportContext */; - } - } - function bindModuleDeclaration(node) { - setExportContextFlag(node); - if (node.name.kind === 9 /* StringLiteral */) { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - } - else { - var state = getModuleInstanceState(node); - if (state === 0 /* NonInstantiated */) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); - } - else { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { - // if module was already merged with some function, class or non-const enum - // treat is a non-const-enum-only - node.symbol.constEnumOnlyModule = false; - } - else { - var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; - if (node.symbol.constEnumOnlyModule === undefined) { - // non-merged case - use the current state - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - // merged case: module is const enum only if all its pieces are non-instantiated or const enum - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } - } - } - } - function bindFunctionOrConstructorType(node) { - // For a given function symbol "<...>(...) => T" we want to generate a symbol identical - // to the one we would get for: { <...>(...): T } - // - // We do that by making an anonymous type literal symbol, and then setting the function - // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable - // from an actual type literal symbol you would have gotten had you used the long form. - var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072 /* Signature */); - var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); - typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); - var _a; - } - function bindObjectLiteralExpression(node) { - var ElementKind; - (function (ElementKind) { - ElementKind[ElementKind["Property"] = 1] = "Property"; - ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; - })(ElementKind || (ElementKind = {})); - if (inStrictMode) { - var seen = {}; - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - if (prop.name.kind !== 69 /* Identifier */) { - continue; - } - var identifier = prop.name; - // ECMA-262 11.1.5 Object Initialiser - // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true - // a.This production is contained in strict code and IsDataDescriptor(previous) is true and - // IsDataDescriptor(propId.descriptor) is true. - // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. - // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. - // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true - // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields - var currentKind = prop.kind === 245 /* PropertyAssignment */ || prop.kind === 246 /* ShorthandPropertyAssignment */ || prop.kind === 143 /* MethodDeclaration */ - ? 1 /* Property */ - : 2 /* Accessor */; - var existingKind = seen[identifier.text]; - if (!existingKind) { - seen[identifier.text] = currentKind; - continue; - } - if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { - var span = ts.getErrorSpanForNode(file, identifier); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); - } - } - } - return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); - } - function bindAnonymousDeclaration(node, symbolFlags, name) { - var symbol = createSymbol(symbolFlags, name); - addDeclarationToSymbol(symbol, node, symbolFlags); - } - function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { - switch (blockScopeContainer.kind) { - case 218 /* ModuleDeclaration */: - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - case 248 /* SourceFile */: - if (ts.isExternalModule(container)) { - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - } - // fall through. - default: - if (!blockScopeContainer.locals) { - blockScopeContainer.locals = {}; - addToContainerChain(blockScopeContainer); - } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); - } - // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized - // check for reserved words used as identifiers in strict mode code. - function checkStrictModeIdentifier(node) { - if (inStrictMode && - node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && - node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && - !ts.isIdentifierName(node)) { - // Report error only if there are no parse errors in file - if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); - } - } - } - function getStrictModeIdentifierMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; - } - function checkStrictModeBinaryExpression(node) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { - // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkStrictModeEvalOrArguments(node, node.left); - } - } - function checkStrictModeCatchClause(node) { - // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the - // Catch production is eval or arguments - if (inStrictMode && node.variableDeclaration) { - checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); - } - } - function checkStrictModeDeleteExpression(node) { - // Grammar checking - if (inStrictMode && node.expression.kind === 69 /* Identifier */) { - // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its - // UnaryExpression is a direct reference to a variable, function argument, or function name - var span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); - } - } - function isEvalOrArgumentsIdentifier(node) { - return node.kind === 69 /* Identifier */ && - (node.text === "eval" || node.text === "arguments"); - } - function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 69 /* Identifier */) { - var identifier = name; - if (isEvalOrArgumentsIdentifier(identifier)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); - } - } - } - function getStrictModeEvalOrArgumentsMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; - } - function checkStrictModeFunctionName(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) - checkStrictModeEvalOrArguments(node, node.name); - } - } - function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.flags & 32768 /* OctalLiteral */) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); - } - } - function checkStrictModePostfixUnaryExpression(node) { - // Grammar checking - // The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression - // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - function checkStrictModePrefixUnaryExpression(node) { - // Grammar checking - if (inStrictMode) { - if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - } - function checkStrictModeWithStatement(node) { - // Grammar checking for withStatement - if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); - } - } - function errorOnFirstToken(node, message, arg0, arg1, arg2) { - var span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); - } - function getDestructuringParameterName(node) { - return "__" + ts.indexOf(node.parent.parameters, node); - } - function bind(node) { - if (!node) { - return; - } - node.parent = parent; - var savedInStrictMode = inStrictMode; - if (!savedInStrictMode) { - updateStrictMode(node); - } - // First we bind declaration nodes to a symbol if possible. We'll both create a symbol - // and then potentially add the symbol to an appropriate symbol table. Possible - // destination symbol tables are: - // - // 1) The 'exports' table of the current container's symbol. - // 2) The 'members' table of the current container's symbol. - // 3) The 'locals' table of the current container. - // - // However, not all symbols will end up in any of these tables. 'Anonymous' symbols - // (like TypeLiterals for example) will not be put in any table. - bindWorker(node); - // Then we recurse into the children of the node to bind them as well. For certain - // symbols we do specialized work when we recurse. For example, we'll keep track of - // the current 'container' node when it changes. This helps us know which symbol table - // a local should go into for example. - bindChildren(node); - inStrictMode = savedInStrictMode; - } - function updateStrictMode(node) { - switch (node.kind) { - case 248 /* SourceFile */: - case 219 /* ModuleBlock */: - updateStrictModeStatementList(node.statements); - return; - case 192 /* Block */: - if (ts.isFunctionLike(node.parent)) { - updateStrictModeStatementList(node.statements); - } - return; - case 214 /* ClassDeclaration */: - case 186 /* ClassExpression */: - // All classes are automatically in strict mode in ES6. - inStrictMode = true; - return; - } - } - function updateStrictModeStatementList(statements) { - for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { - var statement = statements_1[_i]; - if (!ts.isPrologueDirective(statement)) { - return; - } - if (isUseStrictPrologueDirective(statement)) { - inStrictMode = true; - return; - } - } - } - /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node) { - var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); - // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the - // string to contain unicode escapes (as per ES5). - return nodeText === "\"use strict\"" || nodeText === "'use strict'"; - } - function bindWorker(node) { - switch (node.kind) { - case 69 /* Identifier */: - return checkStrictModeIdentifier(node); - case 181 /* BinaryExpression */: - return checkStrictModeBinaryExpression(node); - case 244 /* CatchClause */: - return checkStrictModeCatchClause(node); - case 175 /* DeleteExpression */: - return checkStrictModeDeleteExpression(node); - case 8 /* NumericLiteral */: - return checkStrictModeNumericLiteral(node); - case 180 /* PostfixUnaryExpression */: - return checkStrictModePostfixUnaryExpression(node); - case 179 /* PrefixUnaryExpression */: - return checkStrictModePrefixUnaryExpression(node); - case 205 /* WithStatement */: - return checkStrictModeWithStatement(node); - case 97 /* ThisKeyword */: - seenThisKeyword = true; - return; - case 137 /* TypeParameter */: - return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530912 /* TypeParameterExcludes */); - case 138 /* Parameter */: - return bindParameter(node); - case 211 /* VariableDeclaration */: - case 163 /* BindingElement */: - return bindVariableDeclarationOrBindingElement(node); - case 141 /* PropertyDeclaration */: - case 140 /* PropertySignature */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 107455 /* PropertyExcludes */); - case 245 /* PropertyAssignment */: - case 246 /* ShorthandPropertyAssignment */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 107455 /* PropertyExcludes */); - case 247 /* EnumMember */: - return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 107455 /* EnumMemberExcludes */); - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - // If this is an ObjectLiteralExpression method, then it sits in the same space - // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes - // so that it will conflict with any other object literal members with the same - // name. - return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 107455 /* PropertyExcludes */ : 99263 /* MethodExcludes */); - case 213 /* FunctionDeclaration */: - checkStrictModeFunctionName(node); - return declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); - case 144 /* Constructor */: - return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); - case 145 /* GetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); - case 146 /* SetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - return bindFunctionOrConstructorType(node); - case 155 /* TypeLiteral */: - return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); - case 165 /* ObjectLiteralExpression */: - return bindObjectLiteralExpression(node); - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.text : "__function"; - return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - return bindClassLikeDeclaration(node); - case 215 /* InterfaceDeclaration */: - return bindBlockScopedDeclaration(node, 64 /* Interface */, 792960 /* InterfaceExcludes */); - case 216 /* TypeAliasDeclaration */: - return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793056 /* TypeAliasExcludes */); - case 217 /* EnumDeclaration */: - return bindEnumDeclaration(node); - case 218 /* ModuleDeclaration */: - return bindModuleDeclaration(node); - case 221 /* ImportEqualsDeclaration */: - case 224 /* NamespaceImport */: - case 226 /* ImportSpecifier */: - case 230 /* ExportSpecifier */: - return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - case 223 /* ImportClause */: - return bindImportClause(node); - case 228 /* ExportDeclaration */: - return bindExportDeclaration(node); - case 227 /* ExportAssignment */: - return bindExportAssignment(node); - case 248 /* SourceFile */: - return bindSourceFileIfExternalModule(); - } - } - function bindSourceFileIfExternalModule() { - setExportContextFlag(file); - if (ts.isExternalModule(file)) { - bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); - } - } - function bindExportAssignment(node) { - if (!container.symbol || !container.symbol.exports) { - // Export assignment in some sort of block construct - bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); - } - else if (node.expression.kind === 69 /* Identifier */) { - // An export default clause with an identifier exports all meanings of that identifier - declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* Alias */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); - } - else { - // An export default clause with an expression exports a value - declareSymbol(container.symbol.exports, container.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); - } - } - function bindExportDeclaration(node) { - if (!container.symbol || !container.symbol.exports) { - // Export * in some sort of block construct - bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); - } - else if (!node.exportClause) { - // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); - } - } - function bindImportClause(node) { - if (node.name) { - declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - } - } - function bindClassLikeDeclaration(node) { - if (node.kind === 214 /* ClassDeclaration */) { - bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); - } - else { - var bindingName = node.name ? node.name.text : "__class"; - bindAnonymousDeclaration(node, 32 /* Class */, bindingName); - // Add name of class expression into the map for semantic classifier - if (node.name) { - classifiableNames[node.name.text] = node.name.text; - } - } - var symbol = node.symbol; - // TypeScript 1.0 spec (April 2014): 8.4 - // Every class automatically contains a static property member named 'prototype', the - // type of which is an instantiation of the class type with type Any supplied as a type - // argument for each type parameter. It is an error to explicitly declare a static - // property member with the name 'prototype'. - // - // Note: we check for this here because this class may be merging into a module. The - // module might have an exported variable called 'prototype'. We can't allow that as - // that would clash with the built-in 'prototype' for the class. - var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); - if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { - if (node.name) { - node.name.parent = node; - } - file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); - } - symbol.exports[prototypeSymbol.name] = prototypeSymbol; - prototypeSymbol.parent = symbol; - } - function bindEnumDeclaration(node) { - return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) - : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); - } - function bindVariableDeclarationOrBindingElement(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); - } - if (!ts.isBindingPattern(node.name)) { - if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); - } - else if (ts.isParameterDeclaration(node)) { - // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration - // because its parent chain has already been set up, since parents are set before descending into children. - // - // If node is a binding element in parameter declaration, we need to use ParameterExcludes. - // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration - // For example: - // function foo([a,a]) {} // Duplicate Identifier error - // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter - // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); - } - } - } - function bindParameter(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a - // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) - checkStrictModeEvalOrArguments(node, node.name); - } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); - } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - // If this is a property-parameter, then also declare the property symbol into the - // containing class. - if (node.flags & 56 /* AccessibilityModifier */ && - node.parent.kind === 144 /* Constructor */ && - ts.isClassLike(node.parent.parent)) { - var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */); - } - } - function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") - : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); - } - // reachability checks - function pushNamedLabel(name) { - initializeReachabilityStateIfNecessary(); - if (ts.hasProperty(labelIndexMap, name.text)) { - return false; - } - labelIndexMap[name.text] = labelStack.push(1 /* Unintialized */) - 1; - return true; - } - function pushImplicitLabel() { - initializeReachabilityStateIfNecessary(); - var index = labelStack.push(1 /* Unintialized */) - 1; - implicitLabels.push(index); - return index; - } - function popNamedLabel(label, outerState) { - var index = labelIndexMap[label.text]; - ts.Debug.assert(index !== undefined); - ts.Debug.assert(labelStack.length == index + 1); - labelIndexMap[label.text] = undefined; - setCurrentStateAtLabel(labelStack.pop(), outerState, label); - } - function popImplicitLabel(implicitLabelIndex, outerState) { - if (labelStack.length !== implicitLabelIndex + 1) { - ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); - } - var i = implicitLabels.pop(); - if (implicitLabelIndex !== i) { - ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); - } - setCurrentStateAtLabel(labelStack.pop(), outerState, /*name*/ undefined); - } - function setCurrentStateAtLabel(innerMergedState, outerState, label) { - if (innerMergedState === 1 /* Unintialized */) { - if (label && !options.allowUnusedLabels) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); - } - currentReachabilityState = outerState; - } - else { - currentReachabilityState = or(innerMergedState, outerState); - } - } - function jumpToLabel(label, outerState) { - initializeReachabilityStateIfNecessary(); - var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); - if (index === undefined) { - // reference to unknown label or - // break/continue used outside of loops - return false; - } - var stateAtLabel = labelStack[index]; - labelStack[index] = stateAtLabel === 1 /* Unintialized */ ? outerState : or(stateAtLabel, outerState); - return true; - } - function checkUnreachable(node) { - switch (currentReachabilityState) { - case 4 /* Unreachable */: - var reportError = - // report error on all statements - ts.isStatement(node) || - // report error on class declarations - node.kind === 214 /* ClassDeclaration */ || - // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === 218 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || - // report error on regular enums and const enums if preserveConstEnums is set - (node.kind === 217 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); - if (reportError) { - currentReachabilityState = 8 /* ReportedUnreachable */; - // unreachable code is reported if - // - user has explicitly asked about it AND - // - statement is in not ambient context (statements in ambient context is already an error - // so we should not report extras) AND - // - node is not variable statement OR - // - node is block scoped variable statement OR - // - node is not block scoped variable statement and at least one variable declaration has initializer - // Rationale: we don't want to report errors on non-initialized var's since they are hoisted - // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - var reportUnreachableCode = !options.allowUnreachableCode && - !ts.isInAmbientContext(node) && - (node.kind !== 193 /* VariableStatement */ || - ts.getCombinedNodeFlags(node.declarationList) & 24576 /* BlockScoped */ || - ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); - if (reportUnreachableCode) { - errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); - } - } - case 8 /* ReportedUnreachable */: - return true; - default: - return false; - } - function shouldReportErrorOnModuleDeclaration(node) { - var instanceState = getModuleInstanceState(node); - return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); - } - } - function initializeReachabilityStateIfNecessary() { - if (labelIndexMap) { - return; - } - currentReachabilityState = 2 /* Reachable */; - labelIndexMap = {}; - labelStack = []; - implicitLabels = []; - } - } -})(ts || (ts = {})); -/// /// /* @internal */ var ts; @@ -5812,6 +4503,10 @@ var ts; return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + function isExternalOrCommonJsModule(file) { + return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; + } + ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isDeclarationFile(file) { return (file.flags & 4096 /* DeclarationFile */) !== 0; } @@ -5865,19 +4560,27 @@ var ts; return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; + function getLeadingCommentRangesOfNodeFromText(node, text) { + return ts.getLeadingCommentRanges(text, node.pos); + } + ts.getLeadingCommentRangesOfNodeFromText = getLeadingCommentRangesOfNodeFromText; function getJsDocComments(node, sourceFileOfNode) { + return getJsDocCommentsFromText(node, sourceFileOfNode.text); + } + ts.getJsDocComments = getJsDocComments; + function getJsDocCommentsFromText(node, text) { var commentRanges = (node.kind === 138 /* Parameter */ || node.kind === 137 /* TypeParameter */) ? - ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : - getLeadingCommentRangesOfNode(node, sourceFileOfNode); + ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : + getLeadingCommentRangesOfNodeFromText(node, text); return ts.filter(commentRanges, isJsDocComment); function isJsDocComment(comment) { // True if the comment starts with '/**' but not if it is '/**/' - return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && - sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && - sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47 /* slash */; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 3) !== 47 /* slash */; } } - ts.getJsDocComments = getJsDocComments; + ts.getJsDocCommentsFromText = getJsDocCommentsFromText; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; function isTypeNode(node) { @@ -6464,6 +5167,57 @@ var ts; return node.kind === 221 /* ImportEqualsDeclaration */ && node.moduleReference.kind !== 232 /* ExternalModuleReference */; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; + function isSourceFileJavaScript(file) { + return isInJavaScriptFile(file); + } + ts.isSourceFileJavaScript = isSourceFileJavaScript; + function isInJavaScriptFile(node) { + return node && !!(node.parserContextFlags & 32 /* JavaScriptFile */); + } + ts.isInJavaScriptFile = isInJavaScriptFile; + /** + * Returns true if the node is a CallExpression to the identifier 'require' with + * exactly one string literal argument. + * This function does not test if the node is in a JavaScript file or not. + */ + function isRequireCall(expression) { + // of the form 'require("name")' + return expression.kind === 168 /* CallExpression */ && + expression.expression.kind === 69 /* Identifier */ && + expression.expression.text === "require" && + expression.arguments.length === 1 && + expression.arguments[0].kind === 9 /* StringLiteral */; + } + ts.isRequireCall = isRequireCall; + /** + * Returns true if the node is an assignment to a property on the identifier 'exports'. + * This function does not test if the node is in a JavaScript file or not. + */ + function isExportsPropertyAssignment(expression) { + // of the form 'exports.name = expr' where 'name' and 'expr' are arbitrary + return isInJavaScriptFile(expression) && + (expression.kind === 181 /* BinaryExpression */) && + (expression.operatorToken.kind === 56 /* EqualsToken */) && + (expression.left.kind === 166 /* PropertyAccessExpression */) && + (expression.left.expression.kind === 69 /* Identifier */) && + ((expression.left.expression).text === "exports"); + } + ts.isExportsPropertyAssignment = isExportsPropertyAssignment; + /** + * Returns true if the node is an assignment to the property access expression 'module.exports'. + * This function does not test if the node is in a JavaScript file or not. + */ + function isModuleExportsAssignment(expression) { + // of the form 'module.exports = expr' where 'expr' is arbitrary + return isInJavaScriptFile(expression) && + (expression.kind === 181 /* BinaryExpression */) && + (expression.operatorToken.kind === 56 /* EqualsToken */) && + (expression.left.kind === 166 /* PropertyAccessExpression */) && + (expression.left.expression.kind === 69 /* Identifier */) && + ((expression.left.expression).text === "module") && + (expression.left.name.text === "exports"); + } + ts.isModuleExportsAssignment = isModuleExportsAssignment; function getExternalModuleName(node) { if (node.kind === 222 /* ImportDeclaration */) { return node.moduleSpecifier; @@ -6791,8 +5545,8 @@ var ts; function getFileReferenceFromReferencePath(comment, commentRange) { var simpleReferenceRegEx = /^\/\/\/\s*/gim; - if (simpleReferenceRegEx.exec(comment)) { - if (isNoDefaultLibRegEx.exec(comment)) { + if (simpleReferenceRegEx.test(comment)) { + if (isNoDefaultLibRegEx.test(comment)) { return { isNoDefaultLib: true }; @@ -6834,6 +5588,10 @@ var ts; return isFunctionLike(node) && (node.flags & 256 /* Async */) !== 0 && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; + function isStringOrNumericLiteral(kind) { + return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */; + } + ts.isStringOrNumericLiteral = isStringOrNumericLiteral; /** * A declaration has a dynamic name if both of the following are true: * 1. The declaration has a computed property name @@ -6842,11 +5600,15 @@ var ts; * Symbol. */ function hasDynamicName(declaration) { - return declaration.name && - declaration.name.kind === 136 /* ComputedPropertyName */ && - !isWellKnownSymbolSyntactically(declaration.name.expression); + return declaration.name && isDynamicName(declaration.name); } ts.hasDynamicName = hasDynamicName; + function isDynamicName(name) { + return name.kind === 136 /* ComputedPropertyName */ && + !isStringOrNumericLiteral(name.expression.kind) && + !isWellKnownSymbolSyntactically(name.expression); + } + ts.isDynamicName = isDynamicName; /** * Checks if the expression is of the form: * Symbol.name @@ -7087,11 +5849,11 @@ var ts; } ts.getIndentSize = getIndentSize; function createTextWriter(newLine) { - var output = ""; - var indent = 0; - var lineStart = true; - var lineCount = 0; - var linePos = 0; + var output; + var indent; + var lineStart; + var lineCount; + var linePos; function write(s) { if (s && s.length) { if (lineStart) { @@ -7101,6 +5863,13 @@ var ts; output += s; } } + function reset() { + output = ""; + indent = 0; + lineStart = true; + lineCount = 0; + linePos = 0; + } function rawWrite(s) { if (s !== undefined) { if (lineStart) { @@ -7127,9 +5896,10 @@ var ts; lineStart = true; } } - function writeTextOfNode(sourceFile, node) { - write(getSourceTextOfNodeFromSourceFile(sourceFile, node)); + function writeTextOfNode(text, node) { + write(getTextOfNodeFromSourceText(text, node)); } + reset(); return { write: write, rawWrite: rawWrite, @@ -7142,10 +5912,20 @@ var ts; getTextPos: function () { return output.length; }, getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, - getText: function () { return output; } + getText: function () { return output; }, + reset: reset }; } ts.createTextWriter = createTextWriter; + /** + * Resolves a local path to a path which is absolute to the base of the emit + */ + function getExternalModuleNameFromPath(host, fileName) { + var dir = host.getCurrentDirectory(); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, fileName, dir, function (f) { return host.getCanonicalFileName(f); }, /*isAbsolutePathAnUrl*/ false); + return ts.removeFileExtension(relativePath); + } + ts.getExternalModuleNameFromPath = getExternalModuleNameFromPath; function getOwnEmitOutputFilePath(sourceFile, host, extension) { var compilerOptions = host.getCompilerOptions(); var emitOutputFilePathWithoutExtension; @@ -7174,6 +5954,10 @@ var ts; return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line; } ts.getLineOfLocalPosition = getLineOfLocalPosition; + function getLineOfLocalPositionFromLineMap(lineMap, pos) { + return ts.computeLineAndCharacterOfPosition(lineMap, pos).line; + } + ts.getLineOfLocalPositionFromLineMap = getLineOfLocalPositionFromLineMap; function getFirstConstructorWithBody(node) { return ts.forEach(node.members, function (member) { if (member.kind === 144 /* Constructor */ && nodeIsPresent(member.body)) { @@ -7246,22 +6030,22 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; - function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) { + function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { // If the leading comments start on different line than the start of node, write new line if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) { + getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) { + function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { var emitLeadingSpace = !trailingSeparator; ts.forEach(comments, function (comment) { if (emitLeadingSpace) { writer.write(" "); emitLeadingSpace = false; } - writeComment(currentSourceFile, writer, comment, newLine); + writeComment(text, lineMap, writer, comment, newLine); if (comment.hasTrailingNewLine) { writer.writeLine(); } @@ -7279,7 +6063,7 @@ var ts; * Detached comment is a comment at the top of file or function body that is separated from * the next statement by space. */ - function emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, removeComments) { + function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { @@ -7289,12 +6073,12 @@ var ts; // // var x = 10; if (node.pos === 0) { - leadingComments = ts.filter(ts.getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment); + leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedComment); } } else { // removeComments is false, just get detached as normal and bypass the process to filter comment - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { var detachedComments = []; @@ -7302,8 +6086,8 @@ var ts; for (var _i = 0, leadingComments_1 = leadingComments; _i < leadingComments_1.length; _i++) { var comment = leadingComments_1[_i]; if (lastComment) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end); - var commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); + var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { // There was a blank line between the last comment and this comment. This // comment is not part of the copyright comments. Return what we have so @@ -7318,36 +6102,36 @@ var ts; // All comments look like they could have been part of the copyright header. Make // sure there is at least one blank line between it and the node. If not, it's not // a copyright header. - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, ts.lastOrUndefined(detachedComments).end); - var nodeLine = getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos)); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.lastOrUndefined(detachedComments).end); + var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments - emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); + emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); + emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } } return currentDetachedCommentInfo; function isPinnedComment(comment) { - return currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 33 /* exclamation */; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 33 /* exclamation */; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(currentSourceFile, writer, comment, newLine) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { - var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos); - var lineCount = ts.getLineStarts(currentSourceFile).length; + function writeCommentRange(text, lineMap, writer, comment, newLine) { + if (text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + var lineCount = lineMap.length; var firstCommentLineIndent; for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount - ? currentSourceFile.text.length + 1 - : getStartPositionOfLine(currentLine + 1, currentSourceFile); + ? text.length + 1 + : lineMap[currentLine + 1]; if (pos !== comment.pos) { // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); } // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); @@ -7365,7 +6149,7 @@ var ts; // More right indented comment */ --4 = 8 - 4 + 11 // class c { } // } - var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart); + var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); @@ -7383,45 +6167,45 @@ var ts; } } // Write the comment line text - writeTrimmedCurrentLine(pos, nextLineStart); + writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { // Single line comment of style //.... - writer.write(currentSourceFile.text.substring(comment.pos, comment.end)); - } - function writeTrimmedCurrentLine(pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); - var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, ""); - if (currentLineText) { - // trimmed forward and ending spaces text - writer.write(currentLineText); - if (end !== comment.end) { - writer.writeLine(); - } - } - else { - // Empty string - make sure we write empty line - writer.writeLiteral(newLine); - } - } - function calculateIndent(pos, end) { - var currentLineIndent = 0; - for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) { - if (currentSourceFile.text.charCodeAt(pos) === 9 /* tab */) { - // Tabs = TabSize = indent size and go to next tabStop - currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); - } - else { - // Single space - currentLineIndent++; - } - } - return currentLineIndent; + writer.write(text.substring(comment.pos, comment.end)); } } ts.writeCommentRange = writeCommentRange; + function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { + var end = Math.min(comment.end, nextLineStart - 1); + var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); + if (currentLineText) { + // trimmed forward and ending spaces text + writer.write(currentLineText); + if (end !== comment.end) { + writer.writeLine(); + } + } + else { + // Empty string - make sure we write empty line + writer.writeLiteral(newLine); + } + } + function calculateIndent(text, pos, end) { + var currentLineIndent = 0; + for (; pos < end && ts.isWhiteSpace(text.charCodeAt(pos)); pos++) { + if (text.charCodeAt(pos) === 9 /* tab */) { + // Tabs = TabSize = indent size and go to next tabStop + currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); + } + else { + // Single space + currentLineIndent++; + } + } + return currentLineIndent; + } function modifierToFlag(token) { switch (token) { case 113 /* StaticKeyword */: return 64 /* Static */; @@ -7517,14 +6301,14 @@ var ts; return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function isJavaScript(fileName) { - return ts.fileExtensionIs(fileName, ".js"); + function hasJavaScriptFileExtension(fileName) { + return ts.fileExtensionIs(fileName, ".js") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isJavaScript = isJavaScript; - function isTsx(fileName) { - return ts.fileExtensionIs(fileName, ".tsx"); + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function allowsJsxExpressions(fileName) { + return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isTsx = isTsx; + ts.allowsJsxExpressions = allowsJsxExpressions; /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences * representing the UTF-8 encoding of the character, and return the expanded char code list. @@ -7835,18 +6619,20 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; })(ts || (ts = {})); -/// /// +/// var ts; (function (ts) { - var nodeConstructors = new Array(272 /* Count */); /* @internal */ ts.parseTime = 0; - function getNodeConstructor(kind) { - return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)); - } - ts.getNodeConstructor = getNodeConstructor; + var NodeConstructor; + var SourceFileConstructor; function createNode(kind, pos, end) { - return new (getNodeConstructor(kind))(pos, end); + if (kind === 248 /* SourceFile */) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + } + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + } } ts.createNode = createNode; function visitNode(cbNode, node) { @@ -8269,6 +7055,9 @@ var ts; // up by avoiding the cost of creating/compiling scanners over and over again. var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); var disallowInAndDecoratorContext = 1 /* DisallowIn */ | 4 /* Decorator */; + // capture constructors in 'initializeState' to avoid null checks + var NodeConstructor; + var SourceFileConstructor; var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -8354,13 +7143,16 @@ var ts; // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); + var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; + initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; syntaxCursor = _syntaxCursor; parseDiagnostics = []; @@ -8368,13 +7160,13 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = ts.isJavaScript(fileName) ? 32 /* JavaScriptFile */ : 0 /* None */; + contextFlags = isJavaScriptFile ? 32 /* JavaScriptFile */ : 0 /* None */; parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(ts.isTsx(fileName) ? 1 /* JSX */ : 0 /* Standard */); + scanner.setLanguageVariant(ts.allowsJsxExpressions(fileName) ? 1 /* JSX */ : 0 /* Standard */); } function clearState() { // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. @@ -8389,6 +7181,9 @@ var ts; } function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { sourceFile = createSourceFile(fileName, languageVersion); + if (contextFlags & 32 /* JavaScriptFile */) { + sourceFile.parserContextFlags = 32 /* JavaScriptFile */; + } // Prime the scanner. token = nextToken(); processReferenceComments(sourceFile); @@ -8406,7 +7201,7 @@ var ts; // If this is a javascript file, proactively see if we can get JSDoc comments for // relevant nodes in the file. We'll use these to provide typing informaion if they're // available. - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { addJSDocComments(); } return sourceFile; @@ -8461,15 +7256,16 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion) { - var sourceFile = createNode(248 /* SourceFile */, /*pos*/ 0); - sourceFile.pos = 0; - sourceFile.end = sourceText.length; + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(248 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); + nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 /* DeclarationFile */ : 0; - sourceFile.languageVariant = ts.isTsx(sourceFile.fileName) ? 1 /* JSX */ : 0 /* Standard */; + sourceFile.languageVariant = ts.allowsJsxExpressions(sourceFile.fileName) ? 1 /* JSX */ : 0 /* Standard */; return sourceFile; } function setContextFlag(val, flag) { @@ -8734,12 +7530,13 @@ var ts; return parseExpected(23 /* SemicolonToken */); } } + // note: this function creates only node function createNode(kind, pos) { nodeCount++; if (!(pos >= 0)) { pos = scanner.getStartPos(); } - return new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))(pos, pos); + return new NodeConstructor(kind, pos, pos); } function finishNode(node, end) { node.end = end === undefined ? scanner.getStartPos() : end; @@ -8904,7 +7701,7 @@ var ts; case 12 /* ObjectLiteralMembers */: return token === 19 /* OpenBracketToken */ || token === 37 /* AsteriskToken */ || isLiteralPropertyName(); case 9 /* ObjectBindingElements */: - return isLiteralPropertyName(); + return token === 19 /* OpenBracketToken */ || isLiteralPropertyName(); case 7 /* HeritageClauseElement */: // If we see { } then only consume it as an expression if it is followed by , or { // That way we won't consume the body of a class in its heritage clause. @@ -9584,9 +8381,7 @@ var ts; } function parseParameterType() { if (parseOptional(54 /* ColonToken */)) { - return token === 9 /* StringLiteral */ - ? parseLiteralNode(/*internName*/ true) - : parseType(); + return parseType(); } return undefined; } @@ -9917,6 +8712,8 @@ var ts; // If these are followed by a dot, then parse these out as a dotted type reference instead. var node = tryParse(parseKeywordAndNoDot); return node || parseTypeReferenceOrTypePredicate(); + case 9 /* StringLiteral */: + return parseLiteralNode(/*internName*/ true); case 103 /* VoidKeyword */: case 97 /* ThisKeyword */: return parseTokenNode(); @@ -9946,6 +8743,7 @@ var ts; case 19 /* OpenBracketToken */: case 25 /* LessThanToken */: case 92 /* NewKeyword */: + case 9 /* StringLiteral */: return true; case 17 /* OpenParenToken */: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, @@ -10362,7 +9160,7 @@ var ts; return 1 /* True */; } // This *could* be a parenthesized arrow function. - // Return Unknown to let the caller know. + // Return Unknown to const the caller know. return 2 /* Unknown */; } else { @@ -10448,7 +9246,7 @@ var ts; // user meant to supply a block. For example, if the user wrote: // // a => - // let v = 0; + // const v = 0; // } // // they may be missing an open brace. Check to see if that's the case so we can @@ -10664,7 +9462,6 @@ var ts; var unaryOperator = token; var simpleUnaryExpression = parseSimpleUnaryExpression(); if (token === 38 /* AsteriskAsteriskToken */) { - var diagnostic; var start = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); if (simpleUnaryExpression.kind === 171 /* TypeAssertionExpression */) { parseErrorAtPosition(start, simpleUnaryExpression.end - start, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); @@ -11868,7 +10665,6 @@ var ts; } function parseObjectBindingElement() { var node = createNode(163 /* BindingElement */); - // TODO(andersh): Handle computed properties var tokenIsIdentifier = isIdentifier(); var propertyName = parsePropertyName(); if (tokenIsIdentifier && token !== 54 /* ColonToken */) { @@ -12691,7 +11487,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); var jsDocTypeExpression = parseJSDocTypeExpression(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -12786,6 +11582,7 @@ var ts; case 103 /* VoidKeyword */: return parseTokenNode(); } + // TODO (drosen): Parse string literal types in JSDoc as well. return parseJSDocTypeReference(); } function parseJSDocThisType() { @@ -12957,7 +11754,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); var jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); var diagnostics = parseDiagnostics; clearState(); @@ -13682,6 +12479,1372 @@ var ts; })(InvalidPosition || (InvalidPosition = {})); })(IncrementalParser || (IncrementalParser = {})); })(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + ts.bindTime = 0; + (function (ModuleInstanceState) { + ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; + ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; + ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; + })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); + var ModuleInstanceState = ts.ModuleInstanceState; + var Reachability; + (function (Reachability) { + Reachability[Reachability["Unintialized"] = 1] = "Unintialized"; + Reachability[Reachability["Reachable"] = 2] = "Reachable"; + Reachability[Reachability["Unreachable"] = 4] = "Unreachable"; + Reachability[Reachability["ReportedUnreachable"] = 8] = "ReportedUnreachable"; + })(Reachability || (Reachability = {})); + function or(state1, state2) { + return (state1 | state2) & 2 /* Reachable */ + ? 2 /* Reachable */ + : (state1 & state2) & 8 /* ReportedUnreachable */ + ? 8 /* ReportedUnreachable */ + : 4 /* Unreachable */; + } + function getModuleInstanceState(node) { + // A module is uninstantiated if it contains only + // 1. interface declarations, type alias declarations + if (node.kind === 215 /* InterfaceDeclaration */ || node.kind === 216 /* TypeAliasDeclaration */) { + return 0 /* NonInstantiated */; + } + else if (ts.isConstEnumDeclaration(node)) { + return 2 /* ConstEnumOnly */; + } + else if ((node.kind === 222 /* ImportDeclaration */ || node.kind === 221 /* ImportEqualsDeclaration */) && !(node.flags & 2 /* Export */)) { + return 0 /* NonInstantiated */; + } + else if (node.kind === 219 /* ModuleBlock */) { + var state = 0 /* NonInstantiated */; + ts.forEachChild(node, function (n) { + switch (getModuleInstanceState(n)) { + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching + return false; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state = 2 /* ConstEnumOnly */; + return false; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state = 1 /* Instantiated */; + return true; + } + }); + return state; + } + else if (node.kind === 218 /* ModuleDeclaration */) { + return getModuleInstanceState(node.body); + } + else { + return 1 /* Instantiated */; + } + } + ts.getModuleInstanceState = getModuleInstanceState; + var ContainerFlags; + (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. + ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... + ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... + ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + ContainerFlags[ContainerFlags["HasLocals"] = 4] = "HasLocals"; + // If the current node is a container that also container that also contains locals. Examples: + // + // Functions, Methods, Modules, Source-files. + ContainerFlags[ContainerFlags["IsContainerWithLocals"] = 5] = "IsContainerWithLocals"; + })(ContainerFlags || (ContainerFlags = {})); + var binder = createBinder(); + function bindSourceFile(file, options) { + var start = new Date().getTime(); + binder(file, options); + ts.bindTime += new Date().getTime() - start; + } + ts.bindSourceFile = bindSourceFile; + function createBinder() { + var file; + var options; + var parent; + var container; + var blockScopeContainer; + var lastContainer; + var seenThisKeyword; + // state used by reachability checks + var hasExplicitReturn; + var currentReachabilityState; + var labelStack; + var labelIndexMap; + var implicitLabels; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). + var inStrictMode; + var symbolCount = 0; + var Symbol; + var classifiableNames; + function bindSourceFile(f, opts) { + file = f; + options = opts; + inStrictMode = !!file.externalModuleIndicator; + classifiableNames = {}; + Symbol = ts.objectAllocator.getSymbolConstructor(); + if (!file.locals) { + bind(file); + file.symbolCount = symbolCount; + file.classifiableNames = classifiableNames; + } + parent = undefined; + container = undefined; + blockScopeContainer = undefined; + lastContainer = undefined; + seenThisKeyword = false; + hasExplicitReturn = false; + labelStack = undefined; + labelIndexMap = undefined; + implicitLabels = undefined; + } + return bindSourceFile; + function createSymbol(flags, name) { + symbolCount++; + return new Symbol(flags, name); + } + function addDeclarationToSymbol(symbol, node, symbolFlags) { + symbol.flags |= symbolFlags; + node.symbol = symbol; + if (!symbol.declarations) { + symbol.declarations = []; + } + symbol.declarations.push(node); + if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { + symbol.exports = {}; + } + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { + symbol.members = {}; + } + if (symbolFlags & 107455 /* Value */ && !symbol.valueDeclaration) { + symbol.valueDeclaration = node; + } + } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. + function getDeclarationName(node) { + if (node.name) { + if (node.kind === 218 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */) { + return "\"" + node.name.text + "\""; + } + if (node.name.kind === 136 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; + } + ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); + return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + } + return node.name.text; + } + switch (node.kind) { + case 144 /* Constructor */: + return "__constructor"; + case 152 /* FunctionType */: + case 147 /* CallSignature */: + return "__call"; + case 153 /* ConstructorType */: + case 148 /* ConstructSignature */: + return "__new"; + case 149 /* IndexSignature */: + return "__index"; + case 228 /* ExportDeclaration */: + return "__export"; + case 227 /* ExportAssignment */: + return node.isExportEquals ? "export=" : "default"; + case 181 /* BinaryExpression */: + // Binary expression case is for JS module 'module.exports = expr' + return "export="; + case 213 /* FunctionDeclaration */: + case 214 /* ClassDeclaration */: + return node.flags & 512 /* Default */ ? "default" : undefined; + } + } + function getDisplayName(node) { + return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ + function declareSymbol(symbolTable, parent, node, includes, excludes) { + ts.Debug.assert(!ts.hasDynamicName(node)); + var isDefaultExport = node.flags & 512 /* Default */; + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var symbol; + if (name !== undefined) { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. + symbol = ts.hasProperty(symbolTable, name) + ? symbolTable[name] + : (symbolTable[name] = createSymbol(0 /* None */, name)); + if (name && (includes & 788448 /* Classifiable */)) { + classifiableNames[name] = name; + } + if (symbol.flags & excludes) { + if (node.name) { + node.name.parent = node; + } + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message = symbol.flags & 2 /* BlockScopedVariable */ + ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : ts.Diagnostics.Duplicate_identifier_0; + ts.forEach(symbol.declarations, function (declaration) { + if (declaration.flags & 512 /* Default */) { + message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; + } + }); + ts.forEach(symbol.declarations, function (declaration) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); + }); + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); + symbol = createSymbol(0 /* None */, name); + } + } + else { + symbol = createSymbol(0 /* None */, "__missing"); + } + addDeclarationToSymbol(symbol, node, includes); + symbol.parent = parent; + return symbol; + } + function declareModuleMember(node, symbolFlags, symbolExcludes) { + var hasExportModifier = ts.getCombinedNodeFlags(node) & 2 /* Export */; + if (symbolFlags & 8388608 /* Alias */) { + if (node.kind === 230 /* ExportSpecifier */ || (node.kind === 221 /* ImportEqualsDeclaration */ && hasExportModifier)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, + // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set + // on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + if (hasExportModifier || container.flags & 131072 /* ExportContext */) { + var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | + (symbolFlags & 793056 /* Type */ ? 2097152 /* ExportType */ : 0) | + (symbolFlags & 1536 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); + var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + node.localSymbol = local; + return local; + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. + function bindChildren(node) { + // Before we recurse into a node's chilren, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. + var saveParent = parent; + var saveContainer = container; + var savedBlockScopeContainer = blockScopeContainer; + // This node will now be set as the parent of all of its children as we recurse into them. + parent = node; + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we proactively initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). + // + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. + // + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidently move any stale data forward from + // a previous compilation. + var containerFlags = getContainerFlags(node); + if (containerFlags & 1 /* IsContainer */) { + container = blockScopeContainer = node; + if (containerFlags & 4 /* HasLocals */) { + container.locals = {}; + } + addToContainerChain(container); + } + else if (containerFlags & 2 /* IsBlockScopedContainer */) { + blockScopeContainer = node; + blockScopeContainer.locals = undefined; + } + var savedReachabilityState; + var savedLabelStack; + var savedLabels; + var savedImplicitLabels; + var savedHasExplicitReturn; + var kind = node.kind; + var flags = node.flags; + // reset all reachability check related flags on node (for incremental scenarios) + flags &= ~1572864 /* ReachabilityCheckFlags */; + if (kind === 215 /* InterfaceDeclaration */) { + seenThisKeyword = false; + } + var saveState = kind === 248 /* SourceFile */ || kind === 219 /* ModuleBlock */ || ts.isFunctionLikeKind(kind); + if (saveState) { + savedReachabilityState = currentReachabilityState; + savedLabelStack = labelStack; + savedLabels = labelIndexMap; + savedImplicitLabels = implicitLabels; + savedHasExplicitReturn = hasExplicitReturn; + currentReachabilityState = 2 /* Reachable */; + hasExplicitReturn = false; + labelStack = labelIndexMap = implicitLabels = undefined; + } + bindReachableStatement(node); + if (currentReachabilityState === 2 /* Reachable */ && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { + flags |= 524288 /* HasImplicitReturn */; + if (hasExplicitReturn) { + flags |= 1048576 /* HasExplicitReturn */; + } + } + if (kind === 215 /* InterfaceDeclaration */) { + flags = seenThisKeyword ? flags | 262144 /* ContainsThis */ : flags & ~262144 /* ContainsThis */; + } + node.flags = flags; + if (saveState) { + hasExplicitReturn = savedHasExplicitReturn; + currentReachabilityState = savedReachabilityState; + labelStack = savedLabelStack; + labelIndexMap = savedLabels; + implicitLabels = savedImplicitLabels; + } + container = saveContainer; + parent = saveParent; + blockScopeContainer = savedBlockScopeContainer; + } + /** + * Returns true if node and its subnodes were successfully traversed. + * Returning false means that node was not examined and caller needs to dive into the node himself. + */ + function bindReachableStatement(node) { + if (checkUnreachable(node)) { + ts.forEachChild(node, bind); + return; + } + switch (node.kind) { + case 198 /* WhileStatement */: + bindWhileStatement(node); + break; + case 197 /* DoStatement */: + bindDoStatement(node); + break; + case 199 /* ForStatement */: + bindForStatement(node); + break; + case 200 /* ForInStatement */: + case 201 /* ForOfStatement */: + bindForInOrForOfStatement(node); + break; + case 196 /* IfStatement */: + bindIfStatement(node); + break; + case 204 /* ReturnStatement */: + case 208 /* ThrowStatement */: + bindReturnOrThrow(node); + break; + case 203 /* BreakStatement */: + case 202 /* ContinueStatement */: + bindBreakOrContinueStatement(node); + break; + case 209 /* TryStatement */: + bindTryStatement(node); + break; + case 206 /* SwitchStatement */: + bindSwitchStatement(node); + break; + case 220 /* CaseBlock */: + bindCaseBlock(node); + break; + case 207 /* LabeledStatement */: + bindLabeledStatement(node); + break; + default: + ts.forEachChild(node, bind); + break; + } + } + function bindWhileStatement(n) { + var preWhileState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + var postWhileState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + // bind expressions (don't affect reachability) + bind(n.expression); + currentReachabilityState = preWhileState; + var postWhileLabel = pushImplicitLabel(); + bind(n.statement); + popImplicitLabel(postWhileLabel, postWhileState); + } + function bindDoStatement(n) { + var preDoState = currentReachabilityState; + var postDoLabel = pushImplicitLabel(); + bind(n.statement); + var postDoState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : preDoState; + popImplicitLabel(postDoLabel, postDoState); + // bind expressions (don't affect reachability) + bind(n.expression); + } + function bindForStatement(n) { + var preForState = currentReachabilityState; + var postForLabel = pushImplicitLabel(); + // bind expressions (don't affect reachability) + bind(n.initializer); + bind(n.condition); + bind(n.incrementor); + bind(n.statement); + // for statement is considered infinite when it condition is either omitted or is true keyword + // - for(..;;..) + // - for(..;true;..) + var isInfiniteLoop = (!n.condition || n.condition.kind === 99 /* TrueKeyword */); + var postForState = isInfiniteLoop ? 4 /* Unreachable */ : preForState; + popImplicitLabel(postForLabel, postForState); + } + function bindForInOrForOfStatement(n) { + var preStatementState = currentReachabilityState; + var postStatementLabel = pushImplicitLabel(); + // bind expressions (don't affect reachability) + bind(n.initializer); + bind(n.expression); + bind(n.statement); + popImplicitLabel(postStatementLabel, preStatementState); + } + function bindIfStatement(n) { + // denotes reachability state when entering 'thenStatement' part of the if statement: + // i.e. if condition is false then thenStatement is unreachable + var ifTrueState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + // denotes reachability state when entering 'elseStatement': + // i.e. if condition is true then elseStatement is unreachable + var ifFalseState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + currentReachabilityState = ifTrueState; + // bind expression (don't affect reachability) + bind(n.expression); + bind(n.thenStatement); + if (n.elseStatement) { + var preElseState = currentReachabilityState; + currentReachabilityState = ifFalseState; + bind(n.elseStatement); + currentReachabilityState = or(currentReachabilityState, preElseState); + } + else { + currentReachabilityState = or(currentReachabilityState, ifFalseState); + } + } + function bindReturnOrThrow(n) { + // bind expression (don't affect reachability) + bind(n.expression); + if (n.kind === 204 /* ReturnStatement */) { + hasExplicitReturn = true; + } + currentReachabilityState = 4 /* Unreachable */; + } + function bindBreakOrContinueStatement(n) { + // call bind on label (don't affect reachability) + bind(n.label); + // for continue case touch label so it will be marked a used + var isValidJump = jumpToLabel(n.label, n.kind === 203 /* BreakStatement */ ? currentReachabilityState : 4 /* Unreachable */); + if (isValidJump) { + currentReachabilityState = 4 /* Unreachable */; + } + } + function bindTryStatement(n) { + // catch\finally blocks has the same reachability as try block + var preTryState = currentReachabilityState; + bind(n.tryBlock); + var postTryState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.catchClause); + var postCatchState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.finallyBlock); + // post catch/finally state is reachable if + // - post try state is reachable - control flow can fall out of try block + // - post catch state is reachable - control flow can fall out of catch block + currentReachabilityState = or(postTryState, postCatchState); + } + function bindSwitchStatement(n) { + var preSwitchState = currentReachabilityState; + var postSwitchLabel = pushImplicitLabel(); + // bind expression (don't affect reachability) + bind(n.expression); + bind(n.caseBlock); + var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242 /* DefaultClause */; }); + // post switch state is unreachable if switch is exaustive (has a default case ) and does not have fallthrough from the last case + var postSwitchState = hasDefault && currentReachabilityState !== 2 /* Reachable */ ? 4 /* Unreachable */ : preSwitchState; + popImplicitLabel(postSwitchLabel, postSwitchState); + } + function bindCaseBlock(n) { + var startState = currentReachabilityState; + for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { + var clause = _a[_i]; + currentReachabilityState = startState; + bind(clause); + if (clause.statements.length && currentReachabilityState === 2 /* Reachable */ && options.noFallthroughCasesInSwitch) { + errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); + } + } + } + function bindLabeledStatement(n) { + // call bind on label (don't affect reachability) + bind(n.label); + var ok = pushNamedLabel(n.label); + bind(n.statement); + if (ok) { + popNamedLabel(n.label, currentReachabilityState); + } + } + function getContainerFlags(node) { + switch (node.kind) { + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + case 215 /* InterfaceDeclaration */: + case 217 /* EnumDeclaration */: + case 155 /* TypeLiteral */: + case 165 /* ObjectLiteralExpression */: + return 1 /* IsContainer */; + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + case 213 /* FunctionDeclaration */: + case 144 /* Constructor */: + case 145 /* GetAccessor */: + case 146 /* SetAccessor */: + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + case 218 /* ModuleDeclaration */: + case 248 /* SourceFile */: + case 216 /* TypeAliasDeclaration */: + return 5 /* IsContainerWithLocals */; + case 244 /* CatchClause */: + case 199 /* ForStatement */: + case 200 /* ForInStatement */: + case 201 /* ForOfStatement */: + case 220 /* CaseBlock */: + return 2 /* IsBlockScopedContainer */; + case 192 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Othewise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; + } + return 0 /* None */; + } + function addToContainerChain(next) { + if (lastContainer) { + lastContainer.nextContainer = next; + } + lastContainer = next; + } + function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { + // Just call this directly so that the return type of this function stays "void". + declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); + } + function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { + switch (container.kind) { + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 218 /* ModuleDeclaration */: + return declareModuleMember(node, symbolFlags, symbolExcludes); + case 248 /* SourceFile */: + return declareSourceFileMember(node, symbolFlags, symbolExcludes); + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + return declareClassMember(node, symbolFlags, symbolExcludes); + case 217 /* EnumDeclaration */: + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + case 155 /* TypeLiteral */: + case 165 /* ObjectLiteralExpression */: + case 215 /* InterfaceDeclaration */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). + return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + case 144 /* Constructor */: + case 145 /* GetAccessor */: + case 146 /* SetAccessor */: + case 213 /* FunctionDeclaration */: + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + case 216 /* TypeAliasDeclaration */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree. To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function declareClassMember(node, symbolFlags, symbolExcludes) { + return node.flags & 64 /* Static */ + ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + } + function declareSourceFileMember(node, symbolFlags, symbolExcludes) { + return ts.isExternalModule(file) + ? declareModuleMember(node, symbolFlags, symbolExcludes) + : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + } + function hasExportDeclarations(node) { + var body = node.kind === 248 /* SourceFile */ ? node : node.body; + if (body.kind === 248 /* SourceFile */ || body.kind === 219 /* ModuleBlock */) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var stat = _a[_i]; + if (stat.kind === 228 /* ExportDeclaration */ || stat.kind === 227 /* ExportAssignment */) { + return true; + } + } + } + return false; + } + function setExportContextFlag(node) { + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { + node.flags |= 131072 /* ExportContext */; + } + else { + node.flags &= ~131072 /* ExportContext */; + } + } + function bindModuleDeclaration(node) { + setExportContextFlag(node); + if (node.name.kind === 9 /* StringLiteral */) { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + } + else { + var state = getModuleInstanceState(node); + if (state === 0 /* NonInstantiated */) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { + // if module was already merged with some function, class or non-const enum + // treat is a non-const-enum-only + node.symbol.constEnumOnlyModule = false; + } + else { + var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; + if (node.symbol.constEnumOnlyModule === undefined) { + // non-merged case - use the current state + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; + } + else { + // merged case: module is const enum only if all its pieces are non-instantiated or const enum + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; + } + } + } + } + } + function bindFunctionOrConstructorType(node) { + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); + typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); + var _a; + } + function bindObjectLiteralExpression(node) { + var ElementKind; + (function (ElementKind) { + ElementKind[ElementKind["Property"] = 1] = "Property"; + ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; + })(ElementKind || (ElementKind = {})); + if (inStrictMode) { + var seen = {}; + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (prop.name.kind !== 69 /* Identifier */) { + continue; + } + var identifier = prop.name; + // ECMA-262 11.1.5 Object Initialiser + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 245 /* PropertyAssignment */ || prop.kind === 246 /* ShorthandPropertyAssignment */ || prop.kind === 143 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; + var existingKind = seen[identifier.text]; + if (!existingKind) { + seen[identifier.text] = currentKind; + continue; + } + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { + var span = ts.getErrorSpanForNode(file, identifier); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); + } + } + } + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); + } + function bindAnonymousDeclaration(node, symbolFlags, name) { + var symbol = createSymbol(symbolFlags, name); + addDeclarationToSymbol(symbol, node, symbolFlags); + } + function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { + switch (blockScopeContainer.kind) { + case 218 /* ModuleDeclaration */: + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + case 248 /* SourceFile */: + if (ts.isExternalModule(container)) { + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + } + // fall through. + default: + if (!blockScopeContainer.locals) { + blockScopeContainer.locals = {}; + addToContainerChain(blockScopeContainer); + } + declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function bindBlockScopedVariableDeclaration(node) { + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); + } + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. + function checkStrictModeIdentifier(node) { + if (inStrictMode && + node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && + !ts.isIdentifierName(node)) { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + } + } + } + function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node) { + if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) + checkStrictModeEvalOrArguments(node, node.left); + } + } + function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments + if (inStrictMode && node.variableDeclaration) { + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); + } + } + function checkStrictModeDeleteExpression(node) { + // Grammar checking + if (inStrictMode && node.expression.kind === 69 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name + var span = ts.getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); + } + } + function isEvalOrArgumentsIdentifier(node) { + return node.kind === 69 /* Identifier */ && + (node.text === "eval" || node.text === "arguments"); + } + function checkStrictModeEvalOrArguments(contextNode, name) { + if (name && name.kind === 69 /* Identifier */) { + var identifier = name; + if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var span = ts.getErrorSpanForNode(file, name); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + } + } + } + function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + } + function checkStrictModeFunctionName(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) + checkStrictModeEvalOrArguments(node, node.name); + } + } + function checkStrictModeNumericLiteral(node) { + if (inStrictMode && node.flags & 32768 /* OctalLiteral */) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); + } + } + function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking + if (inStrictMode) { + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + } + function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement + if (inStrictMode) { + errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + } + } + function errorOnFirstToken(node, message, arg0, arg1, arg2) { + var span = ts.getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + } + function getDestructuringParameterName(node) { + return "__" + ts.indexOf(node.parent.parameters, node); + } + function bind(node) { + if (!node) { + return; + } + node.parent = parent; + var savedInStrictMode = inStrictMode; + if (!savedInStrictMode) { + updateStrictMode(node); + } + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // However, not all symbols will end up in any of these tables. 'Anonymous' symbols + // (like TypeLiterals for example) will not be put in any table. + bindWorker(node); + // Then we recurse into the children of the node to bind them as well. For certain + // symbols we do specialized work when we recurse. For example, we'll keep track of + // the current 'container' node when it changes. This helps us know which symbol table + // a local should go into for example. + bindChildren(node); + inStrictMode = savedInStrictMode; + } + function updateStrictMode(node) { + switch (node.kind) { + case 248 /* SourceFile */: + case 219 /* ModuleBlock */: + updateStrictModeStatementList(node.statements); + return; + case 192 /* Block */: + if (ts.isFunctionLike(node.parent)) { + updateStrictModeStatementList(node.statements); + } + return; + case 214 /* ClassDeclaration */: + case 186 /* ClassExpression */: + // All classes are automatically in strict mode in ES6. + inStrictMode = true; + return; + } + } + function updateStrictModeStatementList(statements) { + for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { + var statement = statements_1[_i]; + if (!ts.isPrologueDirective(statement)) { + return; + } + if (isUseStrictPrologueDirective(statement)) { + inStrictMode = true; + return; + } + } + } + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) + function isUseStrictPrologueDirective(node) { + var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). + return nodeText === "\"use strict\"" || nodeText === "'use strict'"; + } + function bindWorker(node) { + switch (node.kind) { + /* Strict mode checks */ + case 69 /* Identifier */: + return checkStrictModeIdentifier(node); + case 181 /* BinaryExpression */: + if (ts.isInJavaScriptFile(node)) { + if (ts.isExportsPropertyAssignment(node)) { + bindExportsPropertyAssignment(node); + } + else if (ts.isModuleExportsAssignment(node)) { + bindModuleExportsAssignment(node); + } + } + return checkStrictModeBinaryExpression(node); + case 244 /* CatchClause */: + return checkStrictModeCatchClause(node); + case 175 /* DeleteExpression */: + return checkStrictModeDeleteExpression(node); + case 8 /* NumericLiteral */: + return checkStrictModeNumericLiteral(node); + case 180 /* PostfixUnaryExpression */: + return checkStrictModePostfixUnaryExpression(node); + case 179 /* PrefixUnaryExpression */: + return checkStrictModePrefixUnaryExpression(node); + case 205 /* WithStatement */: + return checkStrictModeWithStatement(node); + case 97 /* ThisKeyword */: + seenThisKeyword = true; + return; + case 137 /* TypeParameter */: + return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530912 /* TypeParameterExcludes */); + case 138 /* Parameter */: + return bindParameter(node); + case 211 /* VariableDeclaration */: + case 163 /* BindingElement */: + return bindVariableDeclarationOrBindingElement(node); + case 141 /* PropertyDeclaration */: + case 140 /* PropertySignature */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 107455 /* PropertyExcludes */); + case 245 /* PropertyAssignment */: + case 246 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 107455 /* PropertyExcludes */); + case 247 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 107455 /* EnumMemberExcludes */); + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 107455 /* PropertyExcludes */ : 99263 /* MethodExcludes */); + case 213 /* FunctionDeclaration */: + checkStrictModeFunctionName(node); + return declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); + case 144 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 145 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); + case 146 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + return bindFunctionOrConstructorType(node); + case 155 /* TypeLiteral */: + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); + case 165 /* ObjectLiteralExpression */: + return bindObjectLiteralExpression(node); + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + checkStrictModeFunctionName(node); + var bindingName = node.name ? node.name.text : "__function"; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); + case 168 /* CallExpression */: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; + // Members of classes, interfaces, and modules + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + return bindClassLikeDeclaration(node); + case 215 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 792960 /* InterfaceExcludes */); + case 216 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793056 /* TypeAliasExcludes */); + case 217 /* EnumDeclaration */: + return bindEnumDeclaration(node); + case 218 /* ModuleDeclaration */: + return bindModuleDeclaration(node); + // Imports and exports + case 221 /* ImportEqualsDeclaration */: + case 224 /* NamespaceImport */: + case 226 /* ImportSpecifier */: + case 230 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + case 223 /* ImportClause */: + return bindImportClause(node); + case 228 /* ExportDeclaration */: + return bindExportDeclaration(node); + case 227 /* ExportAssignment */: + return bindExportAssignment(node); + case 248 /* SourceFile */: + return bindSourceFileIfExternalModule(); + } + } + function bindSourceFileIfExternalModule() { + setExportContextFlag(file); + if (ts.isExternalModule(file)) { + bindSourceFileAsExternalModule(); + } + } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } + function bindExportAssignment(node) { + var boundExpression = node.kind === 227 /* ExportAssignment */ ? node.expression : node.right; + if (!container.symbol || !container.symbol.exports) { + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); + } + else if (boundExpression.kind === 69 /* Identifier */) { + // An export default clause with an identifier exports all meanings of that identifier + declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* Alias */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + else { + // An export default clause with an expression exports a value + declareSymbol(container.symbol.exports, container.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + } + function bindExportDeclaration(node) { + if (!container.symbol || !container.symbol.exports) { + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); + } + else if (!node.exportClause) { + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); + } + } + function bindImportClause(node) { + if (node.name) { + declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + } + } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); + } + } + function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); + } + function bindModuleExportsAssignment(node) { + // 'module.exports = expr' assignment + setCommonJsModuleIndicator(node); + bindExportAssignment(node); + } + function bindCallExpression(node) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node)) { + setCommonJsModuleIndicator(node); + } + } + function bindClassLikeDeclaration(node) { + if (node.kind === 214 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); + } + else { + var bindingName = node.name ? node.name.text : "__class"; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier + if (node.name) { + classifiableNames[node.name.text] = node.name.text; + } + } + var symbol = node.symbol; + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); + if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { + if (node.name) { + node.name.parent = node; + } + file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); + } + symbol.exports[prototypeSymbol.name] = prototypeSymbol; + prototypeSymbol.parent = symbol; + } + function bindEnumDeclaration(node) { + return ts.isConst(node) + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + } + function bindVariableDeclarationOrBindingElement(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (!ts.isBindingPattern(node.name)) { + if (ts.isBlockOrCatchScoped(node)) { + bindBlockScopedVariableDeclaration(node); + } + else if (ts.isParameterDeclaration(node)) { + // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); + } + } + } + function bindParameter(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) + checkStrictModeEvalOrArguments(node, node.name); + } + if (ts.isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); + } + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + } + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + if (node.flags & 56 /* AccessibilityModifier */ && + node.parent.kind === 144 /* Constructor */ && + ts.isClassLike(node.parent.parent)) { + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */); + } + } + function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { + return ts.hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); + } + // reachability checks + function pushNamedLabel(name) { + initializeReachabilityStateIfNecessary(); + if (ts.hasProperty(labelIndexMap, name.text)) { + return false; + } + labelIndexMap[name.text] = labelStack.push(1 /* Unintialized */) - 1; + return true; + } + function pushImplicitLabel() { + initializeReachabilityStateIfNecessary(); + var index = labelStack.push(1 /* Unintialized */) - 1; + implicitLabels.push(index); + return index; + } + function popNamedLabel(label, outerState) { + var index = labelIndexMap[label.text]; + ts.Debug.assert(index !== undefined); + ts.Debug.assert(labelStack.length == index + 1); + labelIndexMap[label.text] = undefined; + setCurrentStateAtLabel(labelStack.pop(), outerState, label); + } + function popImplicitLabel(implicitLabelIndex, outerState) { + if (labelStack.length !== implicitLabelIndex + 1) { + ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); + } + var i = implicitLabels.pop(); + if (implicitLabelIndex !== i) { + ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); + } + setCurrentStateAtLabel(labelStack.pop(), outerState, /*name*/ undefined); + } + function setCurrentStateAtLabel(innerMergedState, outerState, label) { + if (innerMergedState === 1 /* Unintialized */) { + if (label && !options.allowUnusedLabels) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); + } + currentReachabilityState = outerState; + } + else { + currentReachabilityState = or(innerMergedState, outerState); + } + } + function jumpToLabel(label, outerState) { + initializeReachabilityStateIfNecessary(); + var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); + if (index === undefined) { + // reference to unknown label or + // break/continue used outside of loops + return false; + } + var stateAtLabel = labelStack[index]; + labelStack[index] = stateAtLabel === 1 /* Unintialized */ ? outerState : or(stateAtLabel, outerState); + return true; + } + function checkUnreachable(node) { + switch (currentReachabilityState) { + case 4 /* Unreachable */: + var reportError = + // report error on all statements except empty ones + (ts.isStatement(node) && node.kind !== 194 /* EmptyStatement */) || + // report error on class declarations + node.kind === 214 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 218 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 217 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + if (reportError) { + currentReachabilityState = 8 /* ReportedUnreachable */; + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ + var reportUnreachableCode = !options.allowUnreachableCode && + !ts.isInAmbientContext(node) && + (node.kind !== 193 /* VariableStatement */ || + ts.getCombinedNodeFlags(node.declarationList) & 24576 /* BlockScoped */ || + ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); + if (reportUnreachableCode) { + errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + } + } + case 8 /* ReportedUnreachable */: + return true; + default: + return false; + } + function shouldReportErrorOnModuleDeclaration(node) { + var instanceState = getModuleInstanceState(node); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + } + } + function initializeReachabilityStateIfNecessary() { + if (labelIndexMap) { + return; + } + currentReachabilityState = 2 /* Reachable */; + labelIndexMap = {}; + labelStack = []; + implicitLabels = []; + } + } +})(ts || (ts = {})); /// /* @internal */ var ts; @@ -13755,7 +13918,7 @@ var ts; symbolToString: symbolToString, getAugmentedPropertiesOfType: getAugmentedPropertiesOfType, getRootSymbols: getRootSymbols, - getContextualType: getContextualType, + getContextualType: getApparentTypeOfContextualType, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: getResolvedSignature, getConstantValue: getConstantValue, @@ -14025,7 +14188,7 @@ var ts; return ts.getAncestor(node, 248 /* SourceFile */); } function isGlobalSourceFile(node) { - return node.kind === 248 /* SourceFile */ && !ts.isExternalModule(node); + return node.kind === 248 /* SourceFile */ && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning && ts.hasProperty(symbols, name)) { @@ -14127,15 +14290,24 @@ var ts; } switch (location.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location)) + if (!ts.isExternalOrCommonJsModule(location)) break; case 218 /* ModuleDeclaration */: var moduleExports = getSymbolOfNode(location).exports; if (location.kind === 248 /* SourceFile */ || (location.kind === 218 /* ModuleDeclaration */ && location.name.kind === 9 /* StringLiteral */)) { - // It's an external module. Because of module/namespace merging, a module's exports are in scope, - // yet we never want to treat an export specifier as putting a member in scope. Therefore, - // if the name we find is purely an export specifier, it is not actually considered in scope. + // It's an external module. First see if the module has an export default and if the local + // name of that export default matches. + if (result = moduleExports["default"]) { + var localSymbol = ts.getLocalSymbolForExportDefault(result); + if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { + break loop; + } + result = undefined; + } + // Because of module/namespace merging, a module's exports are in scope, + // yet we never want to treat an export specifier as putting a member in scope. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope. // Two things to note about this: // 1. We have to check this without calling getSymbol. The problem with calling getSymbol // on an export specifier is that it might find the export specifier itself, and try to @@ -14149,12 +14321,6 @@ var ts; ts.getDeclarationOfKind(moduleExports[name], 230 /* ExportSpecifier */)) { break; } - result = moduleExports["default"]; - var localSymbol = ts.getLocalSymbolForExportDefault(result); - if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) { - break loop; - } - result = undefined; } if (result = getSymbol(moduleExports, name, meaning & 8914931 /* ModuleMember */)) { break loop; @@ -14297,7 +14463,7 @@ var ts; // declare module foo { // interface bar {} // } - // let foo/*1*/: foo/*2*/.bar; + // const foo/*1*/: foo/*2*/.bar; // The foo at /*1*/ and /*2*/ will share same symbol with two meaning // block - scope variable and namespace module. However, only when we // try to resolve name in /*1*/ which is used in variable position, @@ -14601,6 +14767,9 @@ var ts; if (moduleName === undefined) { return; } + if (moduleName.indexOf("!") >= 0) { + moduleName = moduleName.substr(0, moduleName.indexOf("!")); + } var isRelative = ts.isExternalModuleNameRelative(moduleName); if (!isRelative) { var symbol = getSymbol(globals, "\"" + moduleName + "\"", 512 /* ValueModule */); @@ -14788,7 +14957,7 @@ var ts; } switch (location_1.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location_1)) { + if (!ts.isExternalOrCommonJsModule(location_1)) { break; } case 218 /* ModuleDeclaration */: @@ -14910,7 +15079,7 @@ var ts; // export class c { // } // } - // let x: typeof m.c + // const x: typeof m.c // In the above example when we start with checking if typeof m.c symbol is accessible, // we are going to see if c can be accessed in scope directly. // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible @@ -14949,7 +15118,7 @@ var ts; } function hasExternalModuleSymbol(declaration) { return (declaration.kind === 218 /* ModuleDeclaration */ && declaration.name.kind === 9 /* StringLiteral */) || - (declaration.kind === 248 /* SourceFile */ && ts.isExternalModule(declaration)); + (declaration.kind === 248 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol) { var aliasesToMakeVisible; @@ -15100,7 +15269,7 @@ var ts; parentSymbol = symbol; appendSymbolNameOnly(symbol, writer); } - // Let the writer know we just wrote out a symbol. The declaration emitter writer uses + // const the writer know we just wrote out a symbol. The declaration emitter writer uses // this to determine if an import it has previously seen (and not written out) needs // to be written to the file once the walk of the tree is complete. // @@ -15181,7 +15350,7 @@ var ts; writeAnonymousType(type, flags); } else if (type.flags & 256 /* StringLiteral */) { - writer.writeStringLiteral(type.text); + writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); } else { // Should never get here @@ -15568,7 +15737,7 @@ var ts; } } else if (node.kind === 248 /* SourceFile */) { - return ts.isExternalModule(node) ? node : undefined; + return ts.isExternalOrCommonJsModule(node) ? node : undefined; } } ts.Debug.fail("getContainingModule cant reach here"); @@ -15650,7 +15819,7 @@ var ts; // Private/protected properties/methods are not visible return false; } - // Public properties/methods are visible if its parents are visible, so let it fall into next case statement + // Public properties/methods are visible if its parents are visible, so const it fall into next case statement case 144 /* Constructor */: case 148 /* ConstructSignature */: case 147 /* CallSignature */: @@ -15678,7 +15847,7 @@ var ts; // Source file is always visible case 248 /* SourceFile */: return true; - // Export assignements do not create name bindings outside the module + // Export assignments do not create name bindings outside the module case 227 /* ExportAssignment */: return false; default: @@ -15814,6 +15983,23 @@ var ts; var symbol = getSymbolOfNode(node); return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node); } + function getTextOfPropertyName(name) { + switch (name.kind) { + case 69 /* Identifier */: + return name.text; + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + return name.text; + case 136 /* ComputedPropertyName */: + if (ts.isStringOrNumericLiteral(name.expression.kind)) { + return name.expression.text; + } + } + return undefined; + } + function isComputedNonLiteralName(name) { + return name.kind === 136 /* ComputedPropertyName */ && !ts.isStringOrNumericLiteral(name.expression.kind); + } // Return the inferred type for a binding element function getTypeForBindingElement(declaration) { var pattern = declaration.parent; @@ -15835,10 +16021,15 @@ var ts; if (pattern.kind === 161 /* ObjectBindingPattern */) { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) var name_10 = declaration.propertyName || declaration.name; + if (isComputedNonLiteralName(name_10)) { + // computed properties with non-literal names are treated as 'any' + return anyType; + } // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. - type = getTypeOfPropertyOfType(parentType, name_10.text) || - isNumericLiteralName(name_10.text) && getIndexTypeOfType(parentType, 1 /* Number */) || + var text = getTextOfPropertyName(name_10); + type = getTypeOfPropertyOfType(parentType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!type) { error(name_10, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_10)); @@ -15938,10 +16129,17 @@ var ts; // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern, includePatternInType) { var members = {}; + var hasComputedProperties = false; ts.forEach(pattern.elements, function (e) { - var flags = 4 /* Property */ | 67108864 /* Transient */ | (e.initializer ? 536870912 /* Optional */ : 0); var name = e.propertyName || e.name; - var symbol = createSymbol(flags, name.text); + if (isComputedNonLiteralName(name)) { + // do not include computed properties in the implied type + hasComputedProperties = true; + return; + } + var text = getTextOfPropertyName(name); + var flags = 4 /* Property */ | 67108864 /* Transient */ | (e.initializer ? 536870912 /* Optional */ : 0); + var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType); symbol.bindingElement = e; members[symbol.name] = symbol; @@ -15950,6 +16148,9 @@ var ts; if (includePatternInType) { result.pattern = pattern; } + if (hasComputedProperties) { + result.flags |= 67108864 /* ObjectLiteralPatternWithComputedProperties */; + } return result; } // Return the type implied by an array binding pattern @@ -16026,6 +16227,14 @@ var ts; if (declaration.kind === 227 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } + // Handle module.exports = expr + if (declaration.kind === 181 /* BinaryExpression */) { + return links.type = checkExpression(declaration.right); + } + // Handle exports.p = expr + if (declaration.kind === 166 /* PropertyAccessExpression */) { + return checkExpressionCached(declaration.parent.right); + } // Handle variable, parameter or property if (!pushTypeResolution(symbol, 0 /* Type */)) { return unknownType; @@ -16304,23 +16513,25 @@ var ts; } function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - var baseContructorType = getBaseConstructorTypeOfClass(type); - if (!(baseContructorType.flags & 80896 /* ObjectType */)) { + var baseConstructorType = getBaseConstructorTypeOfClass(type); + if (!(baseConstructorType.flags & 80896 /* ObjectType */)) { return; } var baseTypeNode = getBaseTypeNodeOfClass(type); var baseType; - if (baseContructorType.symbol && baseContructorType.symbol.flags & 32 /* Class */) { - // When base constructor type is a class we know that the constructors all have the same type parameters as the + var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 /* Class */ && + areAllOuterTypeParametersApplied(originalBaseType)) { + // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the // class and all return the instance type of the class. There is no need for further checks and we can apply the // type arguments in the same manner as a type reference to get the same error reporting experience. - baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol); + baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } else { // The class derives from a "class-like" constructor function, check that we have at least one construct signature // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere // we check that all instantiated signatures return the same type. - var constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments); + var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); return; @@ -16345,6 +16556,17 @@ var ts; type.resolvedBaseTypes.push(baseType); } } + function areAllOuterTypeParametersApplied(type) { + // An unapplied type parameter has its symbol still the same as the matching argument symbol. + // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. + var outerTypeParameters = type.outerTypeParameters; + if (outerTypeParameters) { + var last = outerTypeParameters.length - 1; + var typeArguments = type.typeArguments; + return outerTypeParameters[last].symbol !== typeArguments[last].symbol; + } + return true; + } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { @@ -16424,7 +16646,7 @@ var ts; type.typeArguments = type.typeParameters; type.thisType = createType(512 /* TypeParameter */ | 33554432 /* ThisType */); type.thisType.symbol = symbol; - type.thisType.constraint = getTypeWithThisArgument(type); + type.thisType.constraint = type; } } return links.declaredType; @@ -16939,6 +17161,20 @@ var ts; type = getApparentType(type); return type.flags & 49152 /* UnionOrIntersection */ ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } + /** + * The apparent type of a type parameter is the base constraint instantiated with the type parameter + * as the type argument for the 'this' type. + */ + function getApparentTypeOfTypeParameter(type) { + if (!type.resolvedApparentType) { + var constraintType = getConstraintOfTypeParameter(type); + while (constraintType && constraintType.flags & 512 /* TypeParameter */) { + constraintType = getConstraintOfTypeParameter(constraintType); + } + type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type); + } + return type.resolvedApparentType; + } /** * For a type parameter, return the base constraint of the type parameter. For the string, number, * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the @@ -16946,12 +17182,7 @@ var ts; */ function getApparentType(type) { if (type.flags & 512 /* TypeParameter */) { - do { - type = getConstraintOfTypeParameter(type); - } while (type && type.flags & 512 /* TypeParameter */); - if (!type) { - type = emptyObjectType; - } + type = getApparentTypeOfTypeParameter(type); } if (type.flags & 258 /* StringLike */) { type = globalStringType; @@ -17116,7 +17347,7 @@ var ts; if (node.initializer) { var signatureDeclaration = node.parent; var signature = getSignatureFromDeclaration(signatureDeclaration); - var parameterIndex = signatureDeclaration.parameters.indexOf(node); + var parameterIndex = ts.indexOf(signatureDeclaration.parameters, node); ts.Debug.assert(parameterIndex >= 0); return parameterIndex >= signature.minArgumentCount; } @@ -17217,6 +17448,16 @@ var ts; } return result; } + function resolveExternalModuleTypeByLiteral(name) { + var moduleSym = resolveExternalModuleName(name, name); + if (moduleSym) { + var resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + return getTypeOfSymbol(resolvedModuleSymbol); + } + } + return anyType; + } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { if (!pushTypeResolution(signature, 3 /* ResolvedReturnType */)) { @@ -17740,11 +17981,12 @@ var ts; return links.resolvedType; } function getStringLiteralType(node) { - if (ts.hasProperty(stringLiteralTypes, node.text)) { - return stringLiteralTypes[node.text]; + var text = node.text; + if (ts.hasProperty(stringLiteralTypes, text)) { + return stringLiteralTypes[text]; } - var type = stringLiteralTypes[node.text] = createType(256 /* StringLiteral */); - type.text = ts.getTextOfNode(node); + var type = stringLiteralTypes[text] = createType(256 /* StringLiteral */); + type.text = text; return type; } function getTypeFromStringLiteral(node) { @@ -18265,7 +18507,7 @@ var ts; return false; } function hasExcessProperties(source, target, reportErrors) { - if (someConstituentTypeHasKind(target, 80896 /* ObjectType */)) { + if (!(target.flags & 67108864 /* ObjectLiteralPatternWithComputedProperties */) && someConstituentTypeHasKind(target, 80896 /* ObjectType */)) { for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (!isKnownProperty(target, prop.name)) { @@ -18358,9 +18600,6 @@ var ts; return result; } function typeParameterIdenticalTo(source, target) { - if (source.symbol.name !== target.symbol.name) { - return 0 /* False */; - } // covers case when both type parameters does not have constraint (both equal to noConstraintType) if (source.constraint === target.constraint) { return -1 /* True */; @@ -18852,18 +19091,29 @@ var ts; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } + function isMatchingSignature(source, target, partialMatch) { + // A source signature matches a target signature if the two signatures have the same number of required, + // optional, and rest parameters. + if (source.parameters.length === target.parameters.length && + source.minArgumentCount === target.minArgumentCount && + source.hasRestParameter === target.hasRestParameter) { + return true; + } + // A source signature partially matches a target signature if the target signature has no fewer required + // parameters and no more overall parameters than the source signature (where a signature with a rest + // parameter is always considered to have more overall parameters than one without). + if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (source.hasRestParameter && !target.hasRestParameter || + source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) { + return true; + } + return false; + } function compareSignatures(source, target, partialMatch, ignoreReturnTypes, compareTypes) { if (source === target) { return -1 /* True */; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { - if (!partialMatch || - source.parameters.length < target.parameters.length && !source.hasRestParameter || - source.minArgumentCount > target.minArgumentCount) { - return 0 /* False */; - } + if (!(isMatchingSignature(source, target, partialMatch))) { + return 0 /* False */; } var result = -1 /* True */; if (source.typeParameters && target.typeParameters) { @@ -18957,6 +19207,9 @@ var ts; function isTupleLikeType(type) { return !!getPropertyOfType(type, "0"); } + function isStringLiteralType(type) { + return type.flags & 256 /* StringLiteral */; + } /** * Check if a Type was written as a tuple type literal. * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. @@ -19629,7 +19882,7 @@ var ts; } function narrowTypeByInstanceof(type, expr, assumeTrue) { // Check that type is not any, assumed result is true, and we have variable symbol on the left - if (isTypeAny(type) || !assumeTrue || expr.left.kind !== 69 /* Identifier */ || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || expr.left.kind !== 69 /* Identifier */ || getResolvedSymbol(expr.left) !== symbol) { return type; } // Check that right operand is a function type with a prototype property @@ -19660,6 +19913,12 @@ var ts; } } if (targetType) { + if (!assumeTrue) { + if (type.flags & 16384 /* Union */) { + return getUnionType(ts.filter(type.types, function (t) { return !isTypeSubtypeOf(t, targetType); })); + } + return type; + } return getNarrowedType(type, targetType); } return type; @@ -20129,6 +20388,9 @@ var ts; function getIndexTypeOfContextualType(type, kind) { return applyToContextualType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }); } + function contextualTypeIsStringLiteralType(type) { + return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, isStringLiteralType) : isStringLiteralType(type)); + } // Return true if the given contextual type is a tuple-like type function contextualTypeIsTupleLikeType(type) { return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); @@ -20150,7 +20412,7 @@ var ts; } function getContextualTypeForObjectLiteralElement(element) { var objectLiteral = element.parent; - var type = getContextualType(objectLiteral); + var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!ts.hasDynamicName(element)) { // For a (non-symbol) computed property, there is no reason to look up the name @@ -20173,7 +20435,7 @@ var ts; // type of T. function getContextualTypeForElementExpression(node) { var arrayLiteral = node.parent; - var type = getContextualType(arrayLiteral); + var type = getApparentTypeOfContextualType(arrayLiteral); if (type) { var index = ts.indexOf(arrayLiteral.elements, node); return getTypeOfPropertyOfContextualType(type, "" + index) @@ -20206,11 +20468,28 @@ var ts; } // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. - function getContextualType(node) { - var type = getContextualTypeWorker(node); + function getApparentTypeOfContextualType(node) { + var type = getContextualType(node); return type && getApparentType(type); } - function getContextualTypeWorker(node) { + /** + * Woah! Do you really want to use this function? + * + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, + * you probably meant to use 'getApparentTypeOfContextualType'. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContetxualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. + * + * @param node the expression whose contextual type will be returned. + * @returns the contextual type of an expression. + */ + function getContextualType(node) { if (isInsideWithStatementBody(node)) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; @@ -20285,7 +20564,7 @@ var ts; ts.Debug.assert(node.kind !== 143 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var type = ts.isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node) - : getContextualType(node); + : getApparentTypeOfContextualType(node); if (!type) { return undefined; } @@ -20411,7 +20690,7 @@ var ts; type.pattern = node; return type; } - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting @@ -20494,10 +20773,11 @@ var ts; checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable = {}; var propertiesArray = []; - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === 161 /* ObjectBindingPattern */ || contextualType.pattern.kind === 165 /* ObjectLiteralExpression */); var typeFlags = 0; + var patternWithComputedProperties = false; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var memberDecl = _a[_i]; var member = memberDecl.symbol; @@ -20525,8 +20805,11 @@ var ts; if (isOptional) { prop.flags |= 536870912 /* Optional */; } + if (ts.hasDynamicName(memberDecl)) { + patternWithComputedProperties = true; + } } - else if (contextualTypeHasPattern) { + else if (contextualTypeHasPattern && !(contextualType.flags & 67108864 /* ObjectLiteralPatternWithComputedProperties */)) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. var impliedProp = getPropertyOfType(contextualType, member.name); @@ -20578,7 +20861,7 @@ var ts; var numberIndexType = getIndexType(1 /* Number */); var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType); var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 1048576 /* FreshObjectLiteral */; - result.flags |= 524288 /* ObjectLiteral */ | 4194304 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 14680064 /* PropagatingFlags */); + result.flags |= 524288 /* ObjectLiteral */ | 4194304 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 14680064 /* PropagatingFlags */) | (patternWithComputedProperties ? 67108864 /* ObjectLiteralPatternWithComputedProperties */ : 0); if (inDestructuringPattern) { result.pattern = node; } @@ -21289,7 +21572,7 @@ var ts; // so order how inherited signatures are processed is still preserved. // interface A { (x: string): void } // interface B extends A { (x: 'foo'): string } - // let b: B; + // const b: B; // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function reorderCandidates(signatures, result) { var lastParent; @@ -22247,6 +22530,10 @@ var ts; return anyType; } } + // In JavaScript files, calls to any identifier 'require' are treated as external module imports + if (ts.isInJavaScriptFile(node) && ts.isRequireCall(node)) { + return resolveExternalModuleTypeByLiteral(node.arguments[0]); + } return getReturnTypeOfSignature(signature); } function checkTaggedTemplateExpression(node) { @@ -22257,7 +22544,10 @@ var ts; var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { var widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { + // Permit 'number[] | "foo"' to be asserted to 'string'. + var bothAreStringLike = someConstituentTypeHasKind(targetType, 258 /* StringLike */) && + someConstituentTypeHasKind(widenedType, 258 /* StringLike */); + if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } @@ -22801,19 +23091,26 @@ var ts; for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { var p = properties_3[_i]; if (p.kind === 245 /* PropertyAssignment */ || p.kind === 246 /* ShorthandPropertyAssignment */) { - // TODO(andersh): Computed property support var name_13 = p.name; + if (name_13.kind === 136 /* ComputedPropertyName */) { + checkComputedPropertyName(name_13); + } + if (isComputedNonLiteralName(name_13)) { + continue; + } + var text = getTextOfPropertyName(name_13); var type = isTypeAny(sourceType) ? sourceType - : getTypeOfPropertyOfType(sourceType, name_13.text) || - isNumericLiteralName(name_13.text) && getIndexTypeOfType(sourceType, 1 /* Number */) || + : getTypeOfPropertyOfType(sourceType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(sourceType, 1 /* Number */) || getIndexTypeOfType(sourceType, 0 /* String */); if (type) { if (p.kind === 246 /* ShorthandPropertyAssignment */) { checkDestructuringAssignment(p, type); } else { - checkDestructuringAssignment(p.initializer || name_13, type); + // non-shorthand property assignments should always have initializers + checkDestructuringAssignment(p.initializer, type); } } else { @@ -23014,6 +23311,10 @@ var ts; case 31 /* ExclamationEqualsToken */: case 32 /* EqualsEqualsEqualsToken */: case 33 /* ExclamationEqualsEqualsToken */: + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (someConstituentTypeHasKind(leftType, 258 /* StringLike */) && someConstituentTypeHasKind(rightType, 258 /* StringLike */)) { + return booleanType; + } if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { reportOperatorError(); } @@ -23137,6 +23438,13 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getUnionType([type1, type2]); } + function checkStringLiteralExpression(node) { + var contextualType = getContextualType(node); + if (contextualType && contextualTypeIsStringLiteralType(contextualType)) { + return getStringLiteralType(node); + } + return stringType; + } function checkTemplateExpression(node) { // We just want to check each expressions, but we are unconcerned with // the type of each expression, as any value may be coerced into a string. @@ -23187,7 +23495,7 @@ var ts; if (isInferentialContext(contextualMapper)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(contextualType); if (contextualSignature && !contextualSignature.typeParameters) { @@ -23251,6 +23559,7 @@ var ts; case 183 /* TemplateExpression */: return checkTemplateExpression(node); case 9 /* StringLiteral */: + return checkStringLiteralExpression(node); case 11 /* NoSubstitutionTemplateLiteral */: return stringType; case 10 /* RegularExpressionLiteral */: @@ -24580,7 +24889,7 @@ var ts; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 248 /* SourceFile */ && ts.isExternalModule(parent)) { + if (parent.kind === 248 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent)) { // If the declaration happens to be in external module, report error that require and exports are reserved keywords error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } @@ -24598,15 +24907,15 @@ var ts; // A non-initialized declaration is a no-op as the block declaration will resolve before the var // declaration. the problem is if the declaration has an initializer. this will act as a write to the // block declared value. this is fine for let, but not const. - // Only consider declarations with initializers, uninitialized let declarations will not + // Only consider declarations with initializers, uninitialized const declarations will not // step on a let/const variable. - // Do not consider let and const declarations, as duplicate block-scoped declarations + // Do not consider const and const declarations, as duplicate block-scoped declarations // are handled by the binder. - // We are only looking for let declarations that step on let\const declarations from a + // We are only looking for const declarations that step on let\const declarations from a // different scope. e.g.: // { // const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration - // let x = 0; // symbol for this declaration will be 'symbol' + // const x = 0; // symbol for this declaration will be 'symbol' // } // skip block-scoped variables and parameters if ((ts.getCombinedNodeFlags(node) & 24576 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { @@ -24693,6 +25002,12 @@ var ts; checkExpressionCached(node.initializer); } } + if (node.kind === 163 /* BindingElement */) { + // check computed properties inside property names of binding elements + if (node.propertyName && node.propertyName.kind === 136 /* ComputedPropertyName */) { + checkComputedPropertyName(node.propertyName); + } + } // For a binding pattern, check contained binding elements if (ts.isBindingPattern(node.name)) { ts.forEach(node.name.elements, checkSourceElement); @@ -25176,6 +25491,7 @@ var ts; var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); + var expressionTypeIsStringLike = someConstituentTypeHasKind(expressionType, 258 /* StringLike */); ts.forEach(node.caseBlock.clauses, function (clause) { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause if (clause.kind === 242 /* DefaultClause */ && !hasDuplicateDefaultClause) { @@ -25195,6 +25511,10 @@ var ts; // TypeScript 1.0 spec (April 2014):5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. var caseType = checkExpression(caseClause.expression); + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, 258 /* StringLike */)) { + return; + } if (!isTypeAssignableTo(expressionType, caseType)) { // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); @@ -25659,11 +25979,14 @@ var ts; var enumIsConst = ts.isConst(node); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.name.kind === 136 /* ComputedPropertyName */) { + if (isComputedNonLiteralName(member.name)) { error(member.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums); } - else if (isNumericLiteralName(member.name.text)) { - error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + else { + var text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text)) { + error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + } } var previousEnumMemberIsNonConstant = autoValue === undefined; var initializer = member.initializer; @@ -26305,8 +26628,8 @@ var ts; } // Function and class expression bodies are checked after all statements in the enclosing body. This is // to ensure constructs like the following are permitted: - // let foo = function () { - // let s = foo(); + // const foo = function () { + // const s = foo(); // return "hello"; // } // Here, performing a full type check of the body of the function expression whilst in the process of @@ -26421,8 +26744,12 @@ var ts; if (!(links.flags & 1 /* TypeChecked */)) { // Check whether the file has declared it is the default lib, // and whether the user has specifically chosen to avoid checking it. - if (node.isDefaultLib && compilerOptions.skipDefaultLibCheck) { - return; + if (compilerOptions.skipDefaultLibCheck) { + // If the user specified '--noLib' and a file has a '/// ', + // then we should treat that file as a default lib. + if (node.hasNoDefaultLib) { + return; + } } // Grammar checking checkGrammarSourceFile(node); @@ -26432,7 +26759,7 @@ var ts; potentialThisCollisions.length = 0; ts.forEach(node.statements, checkSourceElement); checkFunctionAndClassExpressionBodies(node); - if (ts.isExternalModule(node)) { + if (ts.isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); } if (potentialThisCollisions.length) { @@ -26515,7 +26842,7 @@ var ts; } switch (location.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location)) { + if (!ts.isExternalOrCommonJsModule(location)) { break; } case 218 /* ModuleDeclaration */: @@ -27153,9 +27480,18 @@ var ts; getReferencedValueDeclaration: getReferencedValueDeclaration, getTypeReferenceSerializationKind: getTypeReferenceSerializationKind, isOptionalParameter: isOptionalParameter, - isArgumentsLocalBinding: isArgumentsLocalBinding + isArgumentsLocalBinding: isArgumentsLocalBinding, + getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration }; } + function getExternalModuleFileFromDeclaration(declaration) { + var specifier = ts.getExternalModuleName(declaration); + var moduleSymbol = getSymbolAtLocation(specifier); + if (!moduleSymbol) { + return undefined; + } + return ts.getDeclarationOfKind(moduleSymbol, 248 /* SourceFile */); + } function initializeTypeChecker() { // Bind all source files and propagate errors ts.forEach(host.getSourceFiles(), function (file) { @@ -27163,11 +27499,10 @@ var ts; }); // Initialize global symbol table ts.forEach(host.getSourceFiles(), function (file) { - if (!ts.isExternalModule(file)) { + if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } }); - // Initialize special symbols getSymbolLinks(undefinedSymbol).type = undefinedType; getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments"); getSymbolLinks(unknownSymbol).type = unknownType; @@ -27866,7 +28201,7 @@ var ts; } } function checkGrammarForNonSymbolComputedProperty(node, message) { - if (node.kind === 136 /* ComputedPropertyName */ && !ts.isWellKnownSymbolSyntactically(node.expression)) { + if (ts.isDynamicName(node)) { return grammarErrorOnNode(node, message); } } @@ -28225,11 +28560,15 @@ var ts; var writeTextOfNode; var writer = createAndSetNewTextWriterWithSymbolWriter(); var enclosingDeclaration; - var currentSourceFile; + var currentText; + var currentLineMap; + var currentIdentifiers; + var isCurrentFileExternalModule; var reportedDeclarationError = false; var errorNameNode; var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments; var emit = compilerOptions.stripInternal ? stripInternal : emitNode; + var noDeclare = !root; var moduleElementDeclarationEmitInfo = []; var asynchronousSubModuleDeclarationEmitInfo; // Contains the reference paths that needs to go in the declaration file. @@ -28272,23 +28611,56 @@ var ts; else { // Emit references corresponding to this file var emittedReferencedFiles = []; + var prevModuleElementDeclarationEmitInfo = []; ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + if (!ts.isDeclarationFile(sourceFile)) { // Check what references need to be added if (!compilerOptions.noResolve) { ts.forEach(sourceFile.referencedFiles, function (fileReference) { var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference); - // If the reference file is a declaration file or an external module, emit that reference - if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) && + // If the reference file is a declaration file, emit that reference + if (referencedFile && (ts.isDeclarationFile(referencedFile) && !ts.contains(emittedReferencedFiles, referencedFile))) { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); } }); } + } + if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + noDeclare = false; emitSourceFile(sourceFile); } + else if (ts.isExternalModule(sourceFile)) { + noDeclare = true; + write("declare module \"" + ts.getResolvedExternalModuleName(host, sourceFile) + "\" {"); + writeLine(); + increaseIndent(); + emitSourceFile(sourceFile); + decreaseIndent(); + write("}"); + writeLine(); + // create asynchronous output for the importDeclarations + if (moduleElementDeclarationEmitInfo.length) { + var oldWriter = writer; + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.isVisible && !aliasEmitInfo.asynchronousOutput) { + ts.Debug.assert(aliasEmitInfo.node.kind === 222 /* ImportDeclaration */); + createAndSetNewTextWriterWithSymbolWriter(); + ts.Debug.assert(aliasEmitInfo.indent === 1); + increaseIndent(); + writeImportDeclaration(aliasEmitInfo.node); + aliasEmitInfo.asynchronousOutput = writer.getText(); + decreaseIndent(); + } + }); + setWriter(oldWriter); + } + prevModuleElementDeclarationEmitInfo = prevModuleElementDeclarationEmitInfo.concat(moduleElementDeclarationEmitInfo); + moduleElementDeclarationEmitInfo = []; + } }); + moduleElementDeclarationEmitInfo = moduleElementDeclarationEmitInfo.concat(prevModuleElementDeclarationEmitInfo); } return { reportedDeclarationError: reportedDeclarationError, @@ -28297,13 +28669,12 @@ var ts; referencePathsOutput: referencePathsOutput }; function hasInternalAnnotation(range) { - var text = currentSourceFile.text; - var comment = text.substring(range.pos, range.end); + var comment = currentText.substring(range.pos, range.end); return comment.indexOf("@internal") >= 0; } function stripInternal(node) { if (node) { - var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + var leadingCommentRanges = ts.getLeadingCommentRanges(currentText, node.pos); if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) { return; } @@ -28395,7 +28766,7 @@ var ts; var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult); if (errorInfo) { if (errorInfo.typeName) { - diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); + diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); } else { diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); @@ -28461,10 +28832,10 @@ var ts; } function writeJsDocComments(declaration) { if (declaration) { - var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile); - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments); + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); } } function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { @@ -28481,7 +28852,7 @@ var ts; case 103 /* VoidKeyword */: case 97 /* ThisKeyword */: case 9 /* StringLiteral */: - return writeTextOfNode(currentSourceFile, type); + return writeTextOfNode(currentText, type); case 188 /* ExpressionWithTypeArguments */: return emitExpressionWithTypeArguments(type); case 151 /* TypeReference */: @@ -28512,14 +28883,14 @@ var ts; } function writeEntityName(entityName) { if (entityName.kind === 69 /* Identifier */) { - writeTextOfNode(currentSourceFile, entityName); + writeTextOfNode(currentText, entityName); } else { var left = entityName.kind === 135 /* QualifiedName */ ? entityName.left : entityName.expression; var right = entityName.kind === 135 /* QualifiedName */ ? entityName.right : entityName.name; writeEntityName(left); write("."); - writeTextOfNode(currentSourceFile, right); + writeTextOfNode(currentText, right); } } function emitEntityName(entityName) { @@ -28549,7 +28920,7 @@ var ts; } } function emitTypePredicate(type) { - writeTextOfNode(currentSourceFile, type.parameterName); + writeTextOfNode(currentText, type.parameterName); write(" is "); emitType(type.type); } @@ -28590,9 +28961,12 @@ var ts; } } function emitSourceFile(node) { - currentSourceFile = node; + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); enclosingDeclaration = node; - ts.emitDetachedComments(currentSourceFile, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); emitLines(node.statements); } // Return a temp variable name to be used in `export default` statements. @@ -28601,13 +28975,13 @@ var ts; // do not need to keep track of created temp names. function getExportDefaultTempVariableName() { var baseName = "_default"; - if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) { + if (!ts.hasProperty(currentIdentifiers, baseName)) { return baseName; } var count = 0; while (true) { var name_18 = baseName + "_" + (++count); - if (!ts.hasProperty(currentSourceFile.identifiers, name_18)) { + if (!ts.hasProperty(currentIdentifiers, name_18)) { return name_18; } } @@ -28615,7 +28989,7 @@ var ts; function emitExportAssignment(node) { if (node.expression.kind === 69 /* Identifier */) { write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentSourceFile, node.expression); + writeTextOfNode(currentText, node.expression); } else { // Expression @@ -28653,7 +29027,7 @@ var ts; writeModuleElement(node); } else if (node.kind === 221 /* ImportEqualsDeclaration */ || - (node.parent.kind === 248 /* SourceFile */ && ts.isExternalModule(currentSourceFile))) { + (node.parent.kind === 248 /* SourceFile */ && isCurrentFileExternalModule)) { var isVisible; if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 248 /* SourceFile */) { // Import declaration of another module that is visited async so lets put it in right spot @@ -28707,7 +29081,7 @@ var ts; } function emitModuleElementDeclarationFlags(node) { // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent === currentSourceFile) { + if (node.parent.kind === 248 /* SourceFile */) { // If the node is exported if (node.flags & 2 /* Export */) { write("export "); @@ -28715,7 +29089,7 @@ var ts; if (node.flags & 512 /* Default */) { write("default "); } - else if (node.kind !== 215 /* InterfaceDeclaration */) { + else if (node.kind !== 215 /* InterfaceDeclaration */ && !noDeclare) { write("declare "); } } @@ -28742,7 +29116,7 @@ var ts; write("export "); } write("import "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" = "); if (ts.isInternalModuleImportEqualsDeclaration(node)) { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); @@ -28750,7 +29124,7 @@ var ts; } else { write("require("); - writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node)); + writeTextOfNode(currentText, ts.getExternalModuleImportEqualsDeclarationExpression(node)); write(");"); } writer.writeLine(); @@ -28785,7 +29159,7 @@ var ts; if (node.importClause) { var currentWriterPos = writer.getTextPos(); if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentSourceFile, node.importClause.name); + writeTextOfNode(currentText, node.importClause.name); } if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { if (currentWriterPos !== writer.getTextPos()) { @@ -28794,7 +29168,7 @@ var ts; } if (node.importClause.namedBindings.kind === 224 /* NamespaceImport */) { write("* as "); - writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name); + writeTextOfNode(currentText, node.importClause.namedBindings.name); } else { write("{ "); @@ -28804,16 +29178,28 @@ var ts; } write(" from "); } - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); write(";"); writer.writeLine(); } + function emitExternalModuleSpecifier(moduleSpecifier) { + if (moduleSpecifier.kind === 9 /* StringLiteral */ && (!root) && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, moduleSpecifier.parent); + if (moduleName) { + write("\""); + write(moduleName); + write("\""); + return; + } + } + writeTextOfNode(currentText, moduleSpecifier); + } function emitImportOrExportSpecifier(node) { if (node.propertyName) { - writeTextOfNode(currentSourceFile, node.propertyName); + writeTextOfNode(currentText, node.propertyName); write(" as "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } function emitExportSpecifier(node) { emitImportOrExportSpecifier(node); @@ -28835,7 +29221,7 @@ var ts; } if (node.moduleSpecifier) { write(" from "); - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); } write(";"); writer.writeLine(); @@ -28849,11 +29235,11 @@ var ts; else { write("module "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); while (node.body.kind !== 219 /* ModuleBlock */) { node = node.body; write("."); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; @@ -28872,7 +29258,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); @@ -28894,7 +29280,7 @@ var ts; write("const "); } write("enum "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" {"); writeLine(); increaseIndent(); @@ -28905,7 +29291,7 @@ var ts; } function emitEnumMemberDeclaration(node) { emitJsDocComments(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var enumMemberValue = resolver.getConstantValue(node); if (enumMemberValue !== undefined) { write(" = "); @@ -28922,7 +29308,7 @@ var ts; increaseIndent(); emitJsDocComments(node); decreaseIndent(); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If there is constraint present and this is not a type parameter of the private method emit the constraint if (node.constraint && !isPrivateMethodTypeParameter(node)) { write(" extends "); @@ -29037,7 +29423,7 @@ var ts; write("abstract "); } write("class "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -29060,7 +29446,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("interface "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -29095,7 +29481,7 @@ var ts; // If this node is a computed name, it can only be a symbol, because we've already skipped // it if it's not a well known symbol. In that case, the text of the name will be exactly // what we want, namely the name expression enclosed in brackets. - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If optional property emit ? if ((node.kind === 141 /* PropertyDeclaration */ || node.kind === 140 /* PropertySignature */) && ts.hasQuestionToken(node)) { write("?"); @@ -29177,7 +29563,7 @@ var ts; emitBindingPattern(bindingElement.name); } else { - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); } } @@ -29221,7 +29607,7 @@ var ts; emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.setAccessor); emitClassMemberDeclarationFlags(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (!(node.flags & 16 /* Private */)) { accessorWithTypeAnnotation = node; var type = getTypeAnnotationFromAccessor(node); @@ -29307,13 +29693,13 @@ var ts; } if (node.kind === 213 /* FunctionDeclaration */) { write("function "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } else if (node.kind === 144 /* Constructor */) { write("constructor"); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (ts.hasQuestionToken(node)) { write("?"); } @@ -29437,7 +29823,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } if (resolver.isOptionalParameter(node)) { write("?"); @@ -29552,7 +29938,7 @@ var ts; // Example: // original: function foo({y: [a,b,c]}) {} // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; - writeTextOfNode(currentSourceFile, bindingElement.propertyName); + writeTextOfNode(currentText, bindingElement.propertyName); write(": "); } if (bindingElement.name) { @@ -29575,7 +29961,7 @@ var ts; if (bindingElement.dotDotDotToken) { write("..."); } - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); } } } @@ -29667,6 +30053,18 @@ var ts; return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile); } ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || ts.isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; var Jump; (function (Jump) { Jump[Jump["Break"] = 2] = "Break"; @@ -29954,15 +30352,19 @@ var ts; var newLine = host.getNewLine(); var jsxDesugaring = host.getCompilerOptions().jsx !== 1 /* Preserve */; var shouldEmitJsx = function (s) { return (s.languageVariant === 1 /* JSX */ && !jsxDesugaring); }; + var outFile = compilerOptions.outFile || compilerOptions.out; + var emitJavaScript = createFileEmitter(); if (targetSourceFile === undefined) { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { - var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); - emitFile(jsFilePath, sourceFile); - } - }); - if (compilerOptions.outFile || compilerOptions.out) { - emitFile(compilerOptions.outFile || compilerOptions.out); + if (outFile) { + emitFile(outFile); + } + else { + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { + var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); + emitFile(jsFilePath, sourceFile); + } + }); } } else { @@ -29971,8 +30373,8 @@ var ts; var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js"); emitFile(jsFilePath, targetSourceFile); } - else if (!ts.isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) { - emitFile(compilerOptions.outFile || compilerOptions.out); + else if (!ts.isDeclarationFile(targetSourceFile) && outFile) { + emitFile(outFile); } } // Sort and make the unique list of diagnostics @@ -30024,10 +30426,16 @@ var ts; } } } - function emitJavaScript(jsFilePath, root) { + function createFileEmitter() { var writer = ts.createTextWriter(newLine); var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; var currentSourceFile; + var currentText; + var currentLineMap; + var currentFileIdentifiers; + var renamedDependencies; + var isEs6Module; + var isCurrentFileExternalModule; // name of an exporter function if file is a System external module // System.register([...], function () {...}) // exporting in System modules looks like: @@ -30035,15 +30443,15 @@ var ts; // => // var x;... exporter("x", x = 1) var exportFunctionForFile; - var generatedNameSet = {}; - var nodeToGeneratedName = []; + var generatedNameSet; + var nodeToGeneratedName; var computedPropertyNamesToGeneratedNames; var convertedLoopState; - var extendsEmitted = false; - var decorateEmitted = false; - var paramEmitted = false; - var awaiterEmitted = false; - var tempFlags = 0; + var extendsEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var tempFlags; var tempVariables; var tempParameters; var externalImports; @@ -30075,6 +30483,8 @@ var ts; var scopeEmitEnd = function () { }; /** Sourcemap data that will get encoded */ var sourceMapData; + /** The root file passed to the emit function (if present) */ + var root; /** If removeComments is true, no leading-comments needed to be emitted **/ var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; var moduleEmitDelegates = (_a = {}, @@ -30085,31 +30495,77 @@ var ts; _a[1 /* CommonJS */] = emitCommonJSModule, _a ); - if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { - initializeEmitterWithSourceMaps(); - } - if (root) { - // Do not call emit directly. It does not set the currentSourceFile. - emitSourceFile(root); - } - else { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - emitSourceFile(sourceFile); + var bundleEmitDelegates = (_b = {}, + _b[5 /* ES6 */] = function () { }, + _b[2 /* AMD */] = emitAMDModule, + _b[4 /* System */] = emitSystemModule, + _b[3 /* UMD */] = function () { }, + _b[1 /* CommonJS */] = function () { }, + _b + ); + return doEmit; + function doEmit(jsFilePath, rootFile) { + // reset the state + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = {}; + nodeToGeneratedName = []; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = rootFile; + if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { + initializeEmitterWithSourceMaps(jsFilePath, root); + } + if (root) { + // Do not call emit directly. It does not set the currentSourceFile. + emitSourceFile(root); + } + else { + if (modulekind) { + ts.forEach(host.getSourceFiles(), emitEmitHelpers); } - }); + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if ((!isExternalModuleOrDeclarationFile(sourceFile)) || (modulekind && ts.isExternalModule(sourceFile))) { + emitSourceFile(sourceFile); + } + }); + } + writeLine(); + writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM); } - writeLine(); - writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM); - return; function emitSourceFile(sourceFile) { currentSourceFile = sourceFile; + currentText = sourceFile.text; + currentLineMap = ts.getLineStarts(sourceFile); exportFunctionForFile = undefined; + isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; + renamedDependencies = sourceFile.renamedDependencies; + currentFileIdentifiers = sourceFile.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(sourceFile); emit(sourceFile); } function isUniqueName(name) { return !resolver.hasGlobalName(name) && - !ts.hasProperty(currentSourceFile.identifiers, name) && + !ts.hasProperty(currentFileIdentifiers, name) && !ts.hasProperty(generatedNameSet, name); } // Return the next available name in the pattern _a ... _z, _0, _1, ... @@ -30192,7 +30648,7 @@ var ts; var id = ts.getNodeId(node); return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); } - function initializeEmitterWithSourceMaps() { + function initializeEmitterWithSourceMaps(jsFilePath, root) { var sourceMapDir; // The directory in which sourcemap will be // Current source map file and its index in the sources list var sourceMapSourceIndex = -1; @@ -30280,7 +30736,7 @@ var ts; } } function recordSourceMapSpan(pos) { - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + var sourceLinePos = ts.computeLineAndCharacterOfPosition(currentLineMap, pos); // Convert the location to be one-based. sourceLinePos.line++; sourceLinePos.character++; @@ -30314,13 +30770,13 @@ var ts; } function recordEmitNodeStartSpan(node) { // Get the token pos after skipping to the token (ignoring the leading trivia) - recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos)); + recordSourceMapSpan(ts.skipTrivia(currentText, node.pos)); } function recordEmitNodeEndSpan(node) { recordSourceMapSpan(node.end); } function writeTextWithSpanRecord(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos); + var tokenStartPos = ts.skipTrivia(currentText, startPos); recordSourceMapSpan(tokenStartPos); var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn); recordSourceMapSpan(tokenEndPos); @@ -30402,9 +30858,9 @@ var ts; sourceMapNameIndices.pop(); } ; - function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) { + function writeCommentRangeWithMap(currentText, currentLineMap, writer, comment, newLine) { recordSourceMapSpan(comment.pos); - ts.writeCommentRange(currentSourceFile, writer, comment, newLine); + ts.writeCommentRange(currentText, currentLineMap, writer, comment, newLine); recordSourceMapSpan(comment.end); } function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings, sourcesContent) { @@ -30434,7 +30890,7 @@ var ts; return output; } } - function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptAndSourceMapFile(emitOutput, jsFilePath, writeByteOrderMark) { encodeLastRecordedSourceMapSpan(); var sourceMapText = serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings, sourceMapData.sourceMapSourcesContent); sourceMapDataList.push(sourceMapData); @@ -30450,7 +30906,7 @@ var ts; sourceMapUrl = "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL; } // Write sourcemap url to the js file and write the js file - writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark); + writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark); } // Initialize source map data var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath)); @@ -30522,7 +30978,7 @@ var ts; scopeEmitEnd = recordScopeNameEnd; writeComment = writeCommentRangeWithMap; } - function writeJavaScriptFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptFile(emitOutput, jsFilePath, writeByteOrderMark) { ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark); } // Create a temporary variable with a unique unused name. @@ -30702,7 +31158,7 @@ var ts; // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. if (node.parent) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + return ts.getTextOfNodeFromSourceText(currentText, node); } // If we can't reach the original source text, use the canonical form if it's a number, // or an escaped quoted form of the original text if it's string-like. @@ -30729,7 +31185,7 @@ var ts; // Find original source text, since we need to emit the raw strings of the tagged template. // The raw strings contain the (escaped) strings of what the user wrote. // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + var text = ts.getTextOfNodeFromSourceText(currentText, node); // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), // thus we need to remove those characters. // First template piece starts with "`", others with "}" @@ -31146,7 +31602,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } write("\""); } @@ -31246,7 +31702,7 @@ var ts; // Identifier references named import write(getGeneratedNameForNode(declaration.parent.parent.parent)); var name_23 = declaration.propertyName || declaration.name; - var identifier = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, name_23); + var identifier = ts.getTextOfNodeFromSourceText(currentText, name_23); if (languageVersion === 0 /* ES3 */ && identifier === "default") { write("[\"default\"]"); } @@ -31270,7 +31726,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function isNameOfNestedRedeclaration(node) { @@ -31308,7 +31764,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function emitThis(node) { @@ -31712,7 +32168,7 @@ var ts; function emitShorthandPropertyAssignment(node) { // The name property of a short-hand property assignment is considered an expression position, so here // we manually emit the identifier to avoid rewriting. - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier, // we emit a normal property assignment. For example: // module m { @@ -31722,7 +32178,7 @@ var ts; // let obj = { y }; // } // Here we need to emit obj = { y : m.y } regardless of the output target. - if (languageVersion < 2 /* ES6 */ || isNamespaceExportReference(node.name)) { + if (modulekind !== 5 /* ES6 */ || isNamespaceExportReference(node.name)) { // Emit identifier as an identifier write(": "); emit(node.name); @@ -31779,11 +32235,11 @@ var ts; var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); // 1 .toString is a valid property access, emit a space after the literal // Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal - var shouldEmitSpace; + var shouldEmitSpace = false; if (!indentedBeforeDot) { if (node.expression.kind === 8 /* NumericLiteral */) { // check if numeric literal was originally written with a dot - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression); + var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); shouldEmitSpace = text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; } else { @@ -32962,16 +33418,16 @@ var ts; emitToken(16 /* CloseBraceToken */, node.clauses.end); } function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, node2.end); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); } function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function emitCaseOrDefaultClause(node) { if (node.kind === 241 /* CaseClause */) { @@ -33077,7 +33533,7 @@ var ts; ts.Debug.assert(!!(node.flags & 512 /* Default */) || node.kind === 227 /* ExportAssignment */); // only allow export default at a source file level if (modulekind === 1 /* CommonJS */ || modulekind === 2 /* AMD */ || modulekind === 3 /* UMD */) { - if (!currentSourceFile.symbol.exports["___esModule"]) { + if (!isEs6Module) { if (languageVersion === 1 /* ES5 */) { // default value of configurable, enumerable, writable are `false`. write("Object.defineProperty(exports, \"__esModule\", { value: true });"); @@ -33272,14 +33728,20 @@ var ts; return node; } function createPropertyAccessForDestructuringProperty(object, propName) { - // We create a synthetic copy of the identifier in order to avoid the rewriting that might - // otherwise occur when the identifier is emitted. - var syntheticName = ts.createSynthesizedNode(propName.kind); - syntheticName.text = propName.text; - if (syntheticName.kind !== 69 /* Identifier */) { - return createElementAccessExpression(object, syntheticName); + var index; + var nameIsComputed = propName.kind === 136 /* ComputedPropertyName */; + if (nameIsComputed) { + index = ensureIdentifier(propName.expression, /* reuseIdentifierExpression */ false); } - return createPropertyAccessExpression(object, syntheticName); + else { + // We create a synthetic copy of the identifier in order to avoid the rewriting that might + // otherwise occur when the identifier is emitted. + index = ts.createSynthesizedNode(propName.kind); + index.text = propName.text; + } + return !nameIsComputed && index.kind === 69 /* Identifier */ + ? createPropertyAccessExpression(object, index) + : createElementAccessExpression(object, index); } function createSliceCall(value, sliceIndex) { var call = ts.createSynthesizedNode(168 /* CallExpression */); @@ -33742,7 +34204,6 @@ var ts; var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); var isArrowFunction = node.kind === 174 /* ArrowFunction */; var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 4096 /* CaptureArguments */) !== 0; - var args; // An async function is emit as an outer function that calls an inner // generator function. To preserve lexical bindings, we pass the current // `this` and `arguments` objects to `__awaiter`. The generator function @@ -35197,8 +35658,8 @@ var ts; * Here we check if alternative name was provided for a given moduleName and return it if possible. */ function tryRenameExternalModule(moduleName) { - if (currentSourceFile.renamedDependencies && ts.hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) { - return "\"" + currentSourceFile.renamedDependencies[moduleName.text] + "\""; + if (renamedDependencies && ts.hasProperty(renamedDependencies, moduleName.text)) { + return "\"" + renamedDependencies[moduleName.text] + "\""; } return undefined; } @@ -35351,7 +35812,7 @@ var ts; // - current file is not external module // - import declaration is top level and target is value imported by entity name if (resolver.isReferencedAliasDeclaration(node) || - (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { + (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { emitLeadingComments(node); emitStart(node); // variable declaration for import-equals declaration can be hoisted in system modules @@ -35579,7 +36040,7 @@ var ts; function getLocalNameForExternalImport(node) { var namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); + return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); } if (node.kind === 222 /* ImportDeclaration */ && node.importClause) { return getGeneratedNameForNode(node); @@ -35884,7 +36345,7 @@ var ts; ts.getEnclosingBlockScopeContainer(node).kind === 248 /* SourceFile */; } function isCurrentFileSystemExternalModule() { - return modulekind === 4 /* System */ && ts.isExternalModule(currentSourceFile); + return modulekind === 4 /* System */ && isCurrentFileExternalModule; } function emitSystemModuleBody(node, dependencyGroups, startIndex) { // shape of the body in system modules: @@ -36054,7 +36515,13 @@ var ts; writeLine(); write("}"); // execute } - function emitSystemModule(node) { + function writeModuleName(node, emitRelativePathAsModuleName) { + var moduleName = node.moduleName; + if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { + write("\"" + moduleName + "\", "); + } + } + function emitSystemModule(node, emitRelativePathAsModuleName) { collectExternalModuleInfo(node); // System modules has the following shape // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) @@ -36069,9 +36536,7 @@ var ts; exportFunctionForFile = makeUniqueName("exports"); writeLine(); write("System.register("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } + writeModuleName(node, emitRelativePathAsModuleName); write("["); var groupIndices = {}; var dependencyGroups = []; @@ -36090,6 +36555,12 @@ var ts; if (i !== 0) { write(", "); } + if (emitRelativePathAsModuleName) { + var name_29 = getExternalModuleNameFromDeclaration(host, resolver, externalImports[i]); + if (name_29) { + text = "\"" + name_29 + "\""; + } + } write(text); } write("], function(" + exportFunctionForFile + ") {"); @@ -36103,7 +36574,7 @@ var ts; writeLine(); write("});"); } - function getAMDDependencyNames(node, includeNonAmdDependencies) { + function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { // names of modules with corresponding parameter in the factory function var aliasedModuleNames = []; // names of modules with no corresponding parameters in factory function @@ -36126,6 +36597,12 @@ var ts; var importNode = externalImports_4[_c]; // Find the name of the external module var externalModuleName = getExternalModuleNameText(importNode); + if (emitRelativePathAsModuleName) { + var name_30 = getExternalModuleNameFromDeclaration(host, resolver, importNode); + if (name_30) { + externalModuleName = "\"" + name_30 + "\""; + } + } // Find the name of the module alias, if there is one var importAliasName = getLocalNameForExternalImport(importNode); if (includeNonAmdDependencies && importAliasName) { @@ -36138,7 +36615,7 @@ var ts; } return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies) { + function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { // An AMD define function has the following shape: // define(id?, dependencies?, factory); // @@ -36150,7 +36627,7 @@ var ts; // To ensure this is true in cases of modules with no aliases, e.g.: // `import "module"` or `` // we need to add modules without alias names to the end of the dependencies list - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies); + var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); emitAMDDependencyList(dependencyNames); write(", "); emitAMDFactoryHeader(dependencyNames); @@ -36177,15 +36654,13 @@ var ts; } write(") {"); } - function emitAMDModule(node) { + function emitAMDModule(node, emitRelativePathAsModuleName) { emitEmitHelpers(node); collectExternalModuleInfo(node); writeLine(); write("define("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } - emitAMDDependencies(node, /*includeNonAmdDependencies*/ true); + writeModuleName(node, emitRelativePathAsModuleName); + emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, emitRelativePathAsModuleName); increaseIndent(); var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true); emitExportStarHelper(); @@ -36404,8 +36879,13 @@ var ts; emitShebang(); emitDetachedCommentsAndUpdateCommentsInfo(node); if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1 /* CommonJS */]; - emitModule(node); + if (root || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { + var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1 /* CommonJS */]; + emitModule(node); + } + else { + bundleEmitDelegates[modulekind](node, /*emitRelativePathAsModuleName*/ true); + } } else { // emit prologue directives prior to __extends @@ -36666,7 +37146,7 @@ var ts; } function getLeadingCommentsWithoutDetachedComments() { // get the leading comments from detachedPos - var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); + var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); } @@ -36683,10 +37163,10 @@ var ts; function isTripleSlashComment(comment) { // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text // so that we don't end up computing comment string and doing match for all // comments - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 /* slash */ && + if (currentText.charCodeAt(comment.pos + 1) === 47 /* slash */ && comment.pos + 2 < comment.end && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 47 /* slash */) { - var textSubStr = currentSourceFile.text.substring(comment.pos, comment.end); + currentText.charCodeAt(comment.pos + 2) === 47 /* slash */) { + var textSubStr = currentText.substring(comment.pos, comment.end); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? true : false; @@ -36703,7 +37183,7 @@ var ts; } else { // get the leading comments from the node - return ts.getLeadingCommentRangesOfNode(node, currentSourceFile); + return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); } } } @@ -36712,7 +37192,7 @@ var ts; // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments if (node.parent) { if (node.parent.kind === 248 /* SourceFile */ || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentSourceFile.text, node.end); + return ts.getTrailingCommentRanges(currentText, node.end); } } } @@ -36746,9 +37226,9 @@ var ts; leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); } } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment); } function emitTrailingComments(node) { if (compilerOptions.removeComments) { @@ -36757,7 +37237,7 @@ var ts; // Emit the trailing comments only if the parent's end doesn't match var trailingComments = getTrailingCommentsToEmit(node); // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); } /** * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: @@ -36768,9 +37248,9 @@ var ts; if (compilerOptions.removeComments) { return; } - var trailingComments = ts.getTrailingCommentRanges(currentSourceFile.text, pos); + var trailingComments = ts.getTrailingCommentRanges(currentText, pos); // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); } function emitLeadingCommentsOfPositionWorker(pos) { if (compilerOptions.removeComments) { @@ -36783,14 +37263,14 @@ var ts; } else { // get the leading comments from the node - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos); + leadingComments = ts.getLeadingCommentRanges(currentText, pos); } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); } function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments); + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -36801,12 +37281,12 @@ var ts; } } function emitShebang() { - var shebang = ts.getShebang(currentSourceFile.text); + var shebang = ts.getShebang(currentText); if (shebang) { write(shebang); } } - var _a; + var _a, _b; } function emitFile(jsFilePath, sourceFile) { emitJavaScript(jsFilePath, sourceFile); @@ -36866,11 +37346,11 @@ var ts; if (ts.getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { var failedLookupLocations = []; var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var resolvedFileName = loadNodeModuleFromFile(ts.supportedJsExtensions, candidate, failedLookupLocations, host); if (resolvedFileName) { return { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations }; } - resolvedFileName = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + resolvedFileName = loadNodeModuleFromDirectory(ts.supportedJsExtensions, candidate, failedLookupLocations, host); return resolvedFileName ? { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations } : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; @@ -36880,8 +37360,8 @@ var ts; } } ts.nodeModuleNameResolver = nodeModuleNameResolver; - function loadNodeModuleFromFile(candidate, failedLookupLocation, host) { - return ts.forEach(ts.moduleFileExtensions, tryLoad); + function loadNodeModuleFromFile(extensions, candidate, failedLookupLocation, host) { + return ts.forEach(extensions, tryLoad); function tryLoad(ext) { var fileName = ts.fileExtensionIs(candidate, ext) ? candidate : candidate + ext; if (host.fileExists(fileName)) { @@ -36893,7 +37373,7 @@ var ts; } } } - function loadNodeModuleFromDirectory(candidate, failedLookupLocation, host) { + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, host) { var packageJsonPath = ts.combinePaths(candidate, "package.json"); if (host.fileExists(packageJsonPath)) { var jsonContent; @@ -36906,7 +37386,7 @@ var ts; jsonContent = { typings: undefined }; } if (jsonContent.typings) { - var result = loadNodeModuleFromFile(ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); + var result = loadNodeModuleFromFile(extensions, ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); if (result) { return result; } @@ -36916,7 +37396,7 @@ var ts; // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocation.push(packageJsonPath); } - return loadNodeModuleFromFile(ts.combinePaths(candidate, "index"), failedLookupLocation, host); + return loadNodeModuleFromFile(extensions, ts.combinePaths(candidate, "index"), failedLookupLocation, host); } function loadModuleFromNodeModules(moduleName, directory, host) { var failedLookupLocations = []; @@ -36926,11 +37406,11 @@ var ts; if (baseName !== "node_modules") { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var result = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var result = loadNodeModuleFromFile(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } - result = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + result = loadNodeModuleFromDirectory(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } @@ -36956,9 +37436,10 @@ var ts; var searchName; var failedLookupLocations = []; var referencedSourceFile; + var extensions = compilerOptions.allowNonTsExtensions ? ts.supportedJsExtensions : ts.supportedExtensions; while (true) { searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleName)); - referencedSourceFile = ts.forEach(ts.supportedExtensions, function (extension) { + referencedSourceFile = ts.forEach(extensions, function (extension) { if (extension === ".tsx" && !compilerOptions.jsx) { // resolve .tsx files only if jsx support is enabled // 'logical not' handles both undefined and None cases @@ -36989,10 +37470,8 @@ var ts; /* @internal */ ts.defaultInitCompilerOptions = { module: 1 /* CommonJS */, - target: 0 /* ES3 */, + target: 1 /* ES5 */, noImplicitAny: false, - outDir: "built", - rootDir: ".", sourceMap: false }; function createCompilerHost(options, setParentNodes) { @@ -37397,43 +37876,55 @@ var ts; if (file.imports) { return; } + var isJavaScriptFile = ts.isSourceFileJavaScript(file); var imports; for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collect(node, /* allowRelativeModuleNames */ true); + collect(node, /* allowRelativeModuleNames */ true, /* collectOnlyRequireCalls */ false); } file.imports = imports || emptyArray; - function collect(node, allowRelativeModuleNames) { - switch (node.kind) { - case 222 /* ImportDeclaration */: - case 221 /* ImportEqualsDeclaration */: - case 228 /* ExportDeclaration */: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + return; + function collect(node, allowRelativeModuleNames, collectOnlyRequireCalls) { + if (!collectOnlyRequireCalls) { + switch (node.kind) { + case 222 /* ImportDeclaration */: + case 221 /* ImportEqualsDeclaration */: + case 228 /* ExportDeclaration */: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + break; + } + if (!moduleNameExpr.text) { + break; + } + if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); + } break; - } - if (!moduleNameExpr.text) { - break; - } - if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 218 /* ModuleDeclaration */: - if (node.name.kind === 9 /* StringLiteral */ && (node.flags & 4 /* Ambient */ || ts.isDeclarationFile(file))) { - // TypeScript 1.0 spec (April 2014): 12.1.6 - // An AmbientExternalModuleDeclaration declares an external module. - // This type of declaration is permitted only in the global module. - // The StringLiteral must specify a top - level external module name. - // Relative external module names are not permitted - ts.forEachChild(node.body, function (node) { + case 218 /* ModuleDeclaration */: + if (node.name.kind === 9 /* StringLiteral */ && (node.flags & 4 /* Ambient */ || ts.isDeclarationFile(file))) { // 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); - }); - } - break; + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + ts.forEachChild(node.body, function (node) { + // 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); + }); + } + break; + } + } + if (isJavaScriptFile) { + if (ts.isRequireCall(node)) { + (imports || (imports = [])).push(node.arguments[0]); + } + else { + ts.forEachChild(node, function (node) { return collect(node, allowRelativeModuleNames, /* collectOnlyRequireCalls */ true); }); + } } } } @@ -37526,7 +38017,6 @@ var ts; // always process imported modules to record module name resolutions processImportedModules(file, basePath); if (isDefaultLib) { - file.isDefaultLib = true; files.unshift(file); } else { @@ -37604,6 +38094,9 @@ var ts; commonPathComponents.length = sourcePathComponents.length; } }); + if (!commonPathComponents) { + return currentDirectory; + } return ts.getNormalizedPathFromPathComponents(commonPathComponents); } function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { @@ -37689,12 +38182,15 @@ var ts; if (options.module === 5 /* ES6 */ && languageVersion < 2 /* ES6 */) { programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower)); } + // Cannot specify module gen that isn't amd or system with --out + if (outFile && options.module && !(options.module === 2 /* AMD */ || options.module === 4 /* System */)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } // there has to be common source directory if user specified --outdir || --sourceRoot // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted if (options.outDir || options.sourceRoot || - (options.mapRoot && - (!outFile || firstExternalModuleSourceFile !== undefined))) { + options.mapRoot) { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { // If a rootDir is specified and is valid use it as the commonSourceDirectory commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); @@ -38212,20 +38708,20 @@ var ts; var exclude = json["exclude"] instanceof Array ? ts.map(json["exclude"], ts.normalizeSlashes) : undefined; var sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); for (var i = 0; i < sysFiles.length; i++) { - var name_29 = sysFiles[i]; - if (ts.fileExtensionIs(name_29, ".d.ts")) { - var baseName = name_29.substr(0, name_29.length - ".d.ts".length); + var name_31 = sysFiles[i]; + if (ts.fileExtensionIs(name_31, ".d.ts")) { + var baseName = name_31.substr(0, name_31.length - ".d.ts".length); if (!ts.contains(sysFiles, baseName + ".tsx") && !ts.contains(sysFiles, baseName + ".ts")) { - fileNames.push(name_29); + fileNames.push(name_31); } } - else if (ts.fileExtensionIs(name_29, ".ts")) { - if (!ts.contains(sysFiles, name_29 + "x")) { - fileNames.push(name_29); + else if (ts.fileExtensionIs(name_31, ".ts")) { + if (!ts.contains(sysFiles, name_31 + "x")) { + fileNames.push(name_31); } } else { - fileNames.push(name_29); + fileNames.push(name_31); } } } @@ -38453,12 +38949,12 @@ var ts; ts.forEach(program.getSourceFiles(), function (sourceFile) { cancellationToken.throwIfCancellationRequested(); var nameToDeclarations = sourceFile.getNamedDeclarations(); - for (var name_30 in nameToDeclarations) { - var declarations = ts.getProperty(nameToDeclarations, name_30); + for (var name_32 in nameToDeclarations) { + var declarations = ts.getProperty(nameToDeclarations, name_32); if (declarations) { // First do a quick check to see if the name of the declaration matches the // last portion of the (possibly) dotted name they're searching for. - var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_30); + var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_32); if (!matches) { continue; } @@ -38471,14 +38967,14 @@ var ts; if (!containers) { return undefined; } - matches = patternMatcher.getMatches(containers, name_30); + matches = patternMatcher.getMatches(containers, name_32); if (!matches) { continue; } } var fileName = sourceFile.fileName; var matchKind = bestMatchKind(matches); - rawItems.push({ name: name_30, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); + rawItems.push({ name: name_32, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); } } } @@ -38859,9 +39355,9 @@ var ts; case 211 /* VariableDeclaration */: case 163 /* BindingElement */: var variableDeclarationNode; - var name_31; + var name_33; if (node.kind === 163 /* BindingElement */) { - name_31 = node.name; + name_33 = node.name; variableDeclarationNode = node; // binding elements are added only for variable declarations // bubble up to the containing variable declaration @@ -38873,16 +39369,16 @@ var ts; else { ts.Debug.assert(!ts.isBindingPattern(node.name)); variableDeclarationNode = node; - name_31 = node.name; + name_33 = node.name; } if (ts.isConst(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.constElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.constElement); } else if (ts.isLet(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.letElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.letElement); } else { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.variableElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.variableElement); } case 144 /* Constructor */: return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement); @@ -39802,7 +40298,7 @@ var ts; if (!candidates.length) { // We didn't have any sig help items produced by the TS compiler. If this is a JS // file, then see if we can figure out anything better. - if (ts.isJavaScript(sourceFile.fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { return createJavaScriptSignatureHelpItems(argumentInfo); } return undefined; @@ -41662,9 +42158,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_32 in o) { - if (o[name_32] === rule) { - return name_32; + for (var name_34 in o) { + if (o[name_34] === rule) { + return name_34; } } throw new Error("Unknown rule"); @@ -42096,7 +42592,7 @@ var ts; function TokenRangeAccess(from, to, except) { this.tokens = []; for (var token = from; token <= to; token++) { - if (except.indexOf(token) < 0) { + if (ts.indexOf(except, token) < 0) { this.tokens.push(token); } } @@ -43709,13 +44205,18 @@ var ts; ]; var jsDocCompletionEntries; function createNode(kind, pos, end, flags, parent) { - var node = new (ts.getNodeConstructor(kind))(pos, end); + var node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; } var NodeObject = (function () { - function NodeObject() { + function NodeObject(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; } NodeObject.prototype.getSourceFile = function () { return ts.getSourceFileOfNode(this); @@ -44198,8 +44699,8 @@ var ts; })(); var SourceFileObject = (function (_super) { __extends(SourceFileObject, _super); - function SourceFileObject() { - _super.apply(this, arguments); + function SourceFileObject(kind, pos, end) { + _super.call(this, kind, pos, end); } SourceFileObject.prototype.update = function (newText, textChangeRange) { return ts.updateSourceFile(this, newText, textChangeRange); @@ -44521,6 +45022,9 @@ var ts; ClassificationTypeNames.typeAliasName = "type alias name"; ClassificationTypeNames.parameterName = "parameter name"; ClassificationTypeNames.docCommentTagName = "doc comment tag name"; + ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; + ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; + ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; @@ -44543,6 +45047,9 @@ var ts; ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; + ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; + ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; + ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; })(ts.ClassificationType || (ts.ClassificationType = {})); var ClassificationType = ts.ClassificationType; function displayPartsToString(displayParts) { @@ -44922,8 +45429,9 @@ var ts; }; } ts.createDocumentRegistry = createDocumentRegistry; - function preProcessFile(sourceText, readImportFiles) { + function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) { if (readImportFiles === void 0) { readImportFiles = true; } + if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } var referencedFiles = []; var importedFiles = []; var ambientExternalModules; @@ -44957,9 +45465,207 @@ var ts; end: pos + importPath.length }); } - function processImport() { + /** + * Returns true if at least one token was consumed from the stream + */ + function tryConsumeDeclare() { + var token = scanner.getToken(); + if (token === 122 /* DeclareKeyword */) { + // declare module "mod" + token = scanner.scan(); + if (token === 125 /* ModuleKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + recordAmbientExternalModule(); + } + } + return true; + } + return false; + } + /** + * Returns true if at least one token was consumed from the stream + */ + function tryConsumeImport() { + var token = scanner.getToken(); + if (token === 89 /* ImportKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import "mod"; + recordModuleName(); + return true; + } + else { + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import d from "mod"; + recordModuleName(); + return true; + } + } + else if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + return true; + } + } + else if (token === 24 /* CommaToken */) { + // consume comma and keep going + token = scanner.scan(); + } + else { + // unknown syntax + return true; + } + } + if (token === 15 /* OpenBraceToken */) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + // make sure that it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = scanner.scan(); + } + if (token === 16 /* CloseBraceToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import {a as A} from "mod"; + // import d, {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = scanner.scan(); + if (token === 116 /* AsKeyword */) { + token = scanner.scan(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import * as NS from "mod" + // import d, * as NS from "mod" + recordModuleName(); + } + } + } + } + } + } + return true; + } + return false; + } + function tryConsumeExport() { + var token = scanner.getToken(); + if (token === 82 /* ExportKeyword */) { + token = scanner.scan(); + if (token === 15 /* OpenBraceToken */) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = scanner.scan(); + } + if (token === 16 /* CloseBraceToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // export * from "mod" + recordModuleName(); + } + } + } + else if (token === 89 /* ImportKeyword */) { + token = scanner.scan(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + return true; + } + } + } + } + return true; + } + return false; + } + function tryConsumeRequireCall(skipCurrentToken) { + var token = skipCurrentToken ? scanner.scan() : scanner.getToken(); + if (token === 127 /* RequireKeyword */) { + token = scanner.scan(); + if (token === 17 /* OpenParenToken */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // require("mod"); + recordModuleName(); + } + } + return true; + } + return false; + } + function tryConsumeDefine() { + var token = scanner.getToken(); + if (token === 69 /* Identifier */ && scanner.getTokenValue() === "define") { + token = scanner.scan(); + if (token !== 17 /* OpenParenToken */) { + return true; + } + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma + token = scanner.scan(); + if (token === 24 /* CommaToken */) { + token = scanner.scan(); + } + else { + // unexpected token + return true; + } + } + // should be start of dependency list + if (token !== 19 /* OpenBracketToken */) { + return true; + } + // skip open bracket + token = scanner.scan(); + var i = 0; + // scan until ']' or EOF + while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { + recordModuleName(); + i++; + } + token = scanner.scan(); + } + return true; + } + return false; + } + function processImports() { scanner.setText(sourceText); - var token = scanner.scan(); + scanner.scan(); // Look for: // import "mod"; // import d from "mod" @@ -44971,152 +45677,26 @@ var ts; // export * from "mod" // export {a as b} from "mod" // export import i = require("mod") - while (token !== 1 /* EndOfFileToken */) { - if (token === 122 /* DeclareKeyword */) { - // declare module "mod" - token = scanner.scan(); - if (token === 125 /* ModuleKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - recordAmbientExternalModule(); - continue; - } - } + // (for JavaScript files) require("mod") + while (true) { + if (scanner.getToken() === 1 /* EndOfFileToken */) { + break; } - else if (token === 89 /* ImportKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import "mod"; - recordModuleName(); - continue; - } - else { - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import d from "mod"; - recordModuleName(); - continue; - } - } - else if (token === 56 /* EqualsToken */) { - token = scanner.scan(); - if (token === 127 /* RequireKeyword */) { - token = scanner.scan(); - if (token === 17 /* OpenParenToken */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import i = require("mod"); - recordModuleName(); - continue; - } - } - } - } - else if (token === 24 /* CommaToken */) { - // consume comma and keep going - token = scanner.scan(); - } - else { - // unknown syntax - continue; - } - } - if (token === 15 /* OpenBraceToken */) { - token = scanner.scan(); - // consume "{ a as B, c, d as D}" clauses - while (token !== 16 /* CloseBraceToken */) { - token = scanner.scan(); - } - if (token === 16 /* CloseBraceToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import {a as A} from "mod"; - // import d, {a, b as B} from "mod" - recordModuleName(); - } - } - } - } - else if (token === 37 /* AsteriskToken */) { - token = scanner.scan(); - if (token === 116 /* AsKeyword */) { - token = scanner.scan(); - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import * as NS from "mod" - // import d, * as NS from "mod" - recordModuleName(); - } - } - } - } - } - } + // check if at least one of alternative have moved scanner forward + if (tryConsumeDeclare() || + tryConsumeImport() || + tryConsumeExport() || + (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + continue; } - else if (token === 82 /* ExportKeyword */) { - token = scanner.scan(); - if (token === 15 /* OpenBraceToken */) { - token = scanner.scan(); - // consume "{ a as B, c, d as D}" clauses - while (token !== 16 /* CloseBraceToken */) { - token = scanner.scan(); - } - if (token === 16 /* CloseBraceToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export {a as A} from "mod"; - // export {a, b as B} from "mod" - recordModuleName(); - } - } - } - } - else if (token === 37 /* AsteriskToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export * from "mod" - recordModuleName(); - } - } - } - else if (token === 89 /* ImportKeyword */) { - token = scanner.scan(); - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 56 /* EqualsToken */) { - token = scanner.scan(); - if (token === 127 /* RequireKeyword */) { - token = scanner.scan(); - if (token === 17 /* OpenParenToken */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export import i = require("mod"); - recordModuleName(); - } - } - } - } - } - } + else { + scanner.scan(); } - token = scanner.scan(); } scanner.setText(undefined); } if (readImportFiles) { - processImport(); + processImports(); } processTripleSlashDirectives(); return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientExternalModules }; @@ -45547,7 +46127,7 @@ var ts; // For JavaScript files, we don't want to report the normal typescript semantic errors. // Instead, we just report errors for using TypeScript-only constructs from within a // JavaScript file. - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(targetSourceFile)) { return getJavaScriptSemanticDiagnostics(targetSourceFile); } // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. @@ -45759,7 +46339,7 @@ var ts; var typeChecker = program.getTypeChecker(); var syntacticStart = new Date().getTime(); var sourceFile = getValidSourceFile(fileName); - var isJavaScriptFile = ts.isJavaScript(fileName); + var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); var isJsDocTagName = false; var start = new Date().getTime(); var currentToken = ts.getTokenAtPosition(sourceFile, position); @@ -46393,8 +46973,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_33 = element.propertyName || element.name; - exisingImportsOrExports[name_33.text] = true; + var name_35 = element.propertyName || element.name; + exisingImportsOrExports[name_35.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -46426,7 +47006,10 @@ var ts; } var existingName = void 0; if (m.kind === 163 /* BindingElement */ && m.propertyName) { - existingName = m.propertyName.text; + // include only identifiers in completion list + if (m.propertyName.kind === 69 /* Identifier */) { + existingName = m.propertyName.text; + } } else { // TODO(jfreeman): Account for computed property name @@ -46466,46 +47049,43 @@ var ts; return undefined; } var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isRightOfDot = completionData.isRightOfDot, isJsDocTagName = completionData.isJsDocTagName; - var entries; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - if (isRightOfDot && ts.isJavaScript(fileName)) { - entries = getCompletionEntriesFromSymbols(symbols); - ts.addRange(entries, getJavaScriptCompletionEntries()); + var sourceFile = getValidSourceFile(fileName); + var entries = []; + if (isRightOfDot && ts.isSourceFileJavaScript(sourceFile)) { + var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); + ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, uniqueNames)); } else { if (!symbols || symbols.length === 0) { return undefined; } - entries = getCompletionEntriesFromSymbols(symbols); + getCompletionEntriesFromSymbols(symbols, entries); } // Add keywords if this is not a member completion list if (!isMemberCompletion && !isJsDocTagName) { ts.addRange(entries, keywordCompletions); } return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries }; - function getJavaScriptCompletionEntries() { + function getJavaScriptCompletionEntries(sourceFile, uniqueNames) { var entries = []; - var allNames = {}; var target = program.getCompilerOptions().target; - for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { - var sourceFile = _a[_i]; - var nameTable = getNameTable(sourceFile); - for (var name_34 in nameTable) { - if (!allNames[name_34]) { - allNames[name_34] = name_34; - var displayName = getCompletionEntryDisplayName(name_34, target, /*performCharacterChecks:*/ true); - if (displayName) { - var entry = { - name: displayName, - kind: ScriptElementKind.warning, - kindModifiers: "", - sortText: "1" - }; - entries.push(entry); - } + var nameTable = getNameTable(sourceFile); + for (var name_36 in nameTable) { + if (!uniqueNames[name_36]) { + uniqueNames[name_36] = name_36; + var displayName = getCompletionEntryDisplayName(name_36, target, /*performCharacterChecks:*/ true); + if (displayName) { + var entry = { + name: displayName, + kind: ScriptElementKind.warning, + kindModifiers: "", + sortText: "1" + }; + entries.push(entry); } } } @@ -46543,25 +47123,24 @@ var ts; sortText: "0" }; } - function getCompletionEntriesFromSymbols(symbols) { + function getCompletionEntriesFromSymbols(symbols, entries) { var start = new Date().getTime(); - var entries = []; + var uniqueNames = {}; if (symbols) { - var nameToSymbol = {}; for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) { var symbol = symbols_3[_i]; var entry = createCompletionEntry(symbol, location); if (entry) { var id = ts.escapeIdentifier(entry.name); - if (!ts.lookUp(nameToSymbol, id)) { + if (!ts.lookUp(uniqueNames, id)) { entries.push(entry); - nameToSymbol[id] = symbol; + uniqueNames[id] = id; } } } } log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start)); - return entries; + return uniqueNames; } } function getCompletionEntryDetails(fileName, position, entryName) { @@ -46762,16 +47341,16 @@ var ts; case ScriptElementKind.parameterElement: case ScriptElementKind.localVariableElement: // If it is call or construct signature of lambda's write type name - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.punctuationPart(ts.SyntaxKind.ColonToken)); displayParts.push(ts.spacePart()); if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); displayParts.push(ts.spacePart()); } - if (!(type.flags & 65536 /* Anonymous */)) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); + if (!(type.flags & ts.TypeFlags.Anonymous)) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, ts.SymbolFormatFlags.WriteTypeParametersOrArguments)); } - addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); + addSignatureDisplayParts(signature, allSignatures, ts.TypeFormatFlags.WriteArrowStyleSignature); break; default: // Just signature @@ -48396,19 +48975,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_35 = node.text; + var name_37 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_35); + var unionProperty = contextualType.getProperty(name_37); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_35); + var symbol = t.getProperty(name_37); if (symbol) { result_4.push(symbol); } @@ -48417,7 +48996,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_35); + var symbol_1 = contextualType.getProperty(name_37); if (symbol_1) { return [symbol_1]; } @@ -48828,6 +49407,9 @@ var ts; case 16 /* typeAliasName */: return ClassificationTypeNames.typeAliasName; case 17 /* parameterName */: return ClassificationTypeNames.parameterName; case 18 /* docCommentTagName */: return ClassificationTypeNames.docCommentTagName; + case 19 /* jsxOpenTagName */: return ClassificationTypeNames.jsxOpenTagName; + case 20 /* jsxCloseTagName */: return ClassificationTypeNames.jsxCloseTagName; + case 21 /* jsxSelfClosingTagName */: return ClassificationTypeNames.jsxSelfClosingTagName; } } function convertClassifications(classifications) { @@ -49097,6 +49679,21 @@ var ts; return 17 /* parameterName */; } return; + case 235 /* JsxOpeningElement */: + if (token.parent.tagName === token) { + return 19 /* jsxOpenTagName */; + } + return; + case 237 /* JsxClosingElement */: + if (token.parent.tagName === token) { + return 20 /* jsxCloseTagName */; + } + return; + case 234 /* JsxSelfClosingElement */: + if (token.parent.tagName === token) { + return 21 /* jsxSelfClosingTagName */; + } + return; } } return 2 /* identifier */; @@ -50021,18 +50618,8 @@ var ts; ts.getDefaultLibFilePath = getDefaultLibFilePath; function initializeServices() { ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - } - var proto = kind === 248 /* SourceFile */ ? new SourceFileObject() : new NodeObject(); - proto.kind = kind; - Node.prototype = proto; - return Node; - }, + getNodeConstructor: function () { return NodeObject; }, + getSourceFileConstructor: function () { return SourceFileObject; }, getSymbolConstructor: function () { return SymbolObject; }, getTypeConstructor: function () { return TypeObject; }, getSignatureConstructor: function () { return SignatureObject; } @@ -51102,7 +51689,8 @@ var ts; }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { - var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength())); + // for now treat files as JavaScript + var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true); var convertResult = { referencedFiles: [], importedFiles: [], @@ -51166,7 +51754,7 @@ var ts; TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) { try { if (this.documentRegistry === undefined) { - this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry); @@ -51199,7 +51787,7 @@ var ts; TypeScriptServicesFactory.prototype.close = function () { // Forget all the registered shims this._shims = []; - this.documentRegistry = ts.createDocumentRegistry(); + this.documentRegistry = undefined; }; TypeScriptServicesFactory.prototype.registerShim = function (shim) { this._shims.push(shim); diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index d2758e6d5e9..af9a8bffe35 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -387,6 +387,7 @@ declare namespace ts { right: Identifier; } type EntityName = Identifier | QualifiedName; + type PropertyName = Identifier | LiteralExpression | ComputedPropertyName; type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName | BindingPattern; interface Declaration extends Node { _declarationBrand: any; @@ -425,7 +426,7 @@ declare namespace ts { initializer?: Expression; } interface BindingElement extends Declaration { - propertyName?: Identifier; + propertyName?: PropertyName; dotDotDotToken?: Node; name: Identifier | BindingPattern; initializer?: Expression; @@ -452,7 +453,7 @@ declare namespace ts { objectAssignmentInitializer?: Expression; } interface VariableLikeDeclaration extends Declaration { - propertyName?: Identifier; + propertyName?: PropertyName; dotDotDotToken?: Node; name: DeclarationName; questionToken?: Node; @@ -581,7 +582,7 @@ declare namespace ts { asteriskToken?: Node; expression?: Expression; } - interface BinaryExpression extends Expression { + interface BinaryExpression extends Expression, Declaration { left: Expression; operatorToken: Node; right: Expression; @@ -625,7 +626,7 @@ declare namespace ts { interface ObjectLiteralExpression extends PrimaryExpression, Declaration { properties: NodeArray; } - interface PropertyAccessExpression extends MemberExpression { + interface PropertyAccessExpression extends MemberExpression, Declaration { expression: LeftHandSideExpression; dotToken: Node; name: Identifier; @@ -1220,6 +1221,7 @@ declare namespace ts { ObjectLiteral = 524288, ESSymbol = 16777216, ThisType = 33554432, + ObjectLiteralPatternWithComputedProperties = 67108864, StringLike = 258, NumberLike = 132, ObjectType = 80896, @@ -1537,7 +1539,6 @@ declare namespace ts { function getTypeParameterOwner(d: Declaration): Declaration; } declare namespace ts { - function getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node; function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean): SourceFile; @@ -2126,6 +2127,9 @@ declare namespace ts { static typeAliasName: string; static parameterName: string; static docCommentTagName: string; + static jsxOpenTagName: string; + static jsxCloseTagName: string; + static jsxSelfClosingTagName: string; } enum ClassificationType { comment = 1, @@ -2146,6 +2150,9 @@ declare namespace ts { typeAliasName = 16, parameterName = 17, docCommentTagName = 18, + jsxOpenTagName = 19, + jsxCloseTagName = 20, + jsxSelfClosingTagName = 21, } interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; @@ -2171,7 +2178,7 @@ declare namespace ts { function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string; function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; - function preProcessFile(sourceText: string, readImportFiles?: boolean): PreProcessedFileInfo; + function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService; function createClassifier(): Classifier; /** diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 8b0ef04f96e..498ddc37860 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -622,6 +622,7 @@ var ts; TypeFlags[TypeFlags["ContainsAnyFunctionType"] = 8388608] = "ContainsAnyFunctionType"; TypeFlags[TypeFlags["ESSymbol"] = 16777216] = "ESSymbol"; TypeFlags[TypeFlags["ThisType"] = 33554432] = "ThisType"; + TypeFlags[TypeFlags["ObjectLiteralPatternWithComputedProperties"] = 67108864] = "ObjectLiteralPatternWithComputedProperties"; /* @internal */ TypeFlags[TypeFlags["Intrinsic"] = 16777343] = "Intrinsic"; /* @internal */ @@ -1530,12 +1531,7 @@ var ts; * List of supported extensions in order of file resolution precedence. */ ts.supportedExtensions = [".ts", ".tsx", ".d.ts"]; - /** - * List of extensions that will be used to look for external modules. - * This list is kept separate from supportedExtensions to for cases when we'll allow to include .js files in compilation, - * but still would like to load only TypeScript files as modules - */ - ts.moduleFileExtensions = ts.supportedExtensions; + ts.supportedJsExtensions = ts.supportedExtensions.concat(".js", ".jsx"); function isSupportedSourceFileName(fileName) { if (!fileName) { return false; @@ -1586,17 +1582,16 @@ var ts; } function Signature(checker) { } + function Node(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; + } ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - } - Node.prototype = { kind: kind }; - return Node; - }, + getNodeConstructor: function () { return Node; }, + getSourceFileConstructor: function () { return Node; }, getSymbolConstructor: function () { return Symbol; }, getTypeConstructor: function () { return Type; }, getSignatureConstructor: function () { return Signature; } @@ -1913,7 +1908,16 @@ var ts; if (writeByteOrderMark) { data = "\uFEFF" + data; } - _fs.writeFileSync(fileName, data, "utf8"); + var fd; + try { + fd = _fs.openSync(fileName, "w"); + _fs.writeSync(fd, data, undefined, "utf8"); + } + finally { + if (fd !== undefined) { + _fs.closeSync(fd); + } + } } function getCanonicalPath(path) { return useCaseSensitiveFileNames ? path.toLowerCase() : path; @@ -2614,6 +2618,7 @@ var ts; Disallow_inconsistently_cased_references_to_the_same_file: { code: 6078, category: ts.DiagnosticCategory.Message, key: "Disallow_inconsistently_cased_references_to_the_same_file_6078", message: "Disallow inconsistently-cased references to the same file." }, Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: ts.DiagnosticCategory.Message, key: "Specify_JSX_code_generation_Colon_preserve_or_react_6080", message: "Specify JSX code generation: 'preserve' or 'react'" }, Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: ts.DiagnosticCategory.Message, key: "Argument_for_jsx_must_be_preserve_or_react_6081", message: "Argument for '--jsx' must be 'preserve' or 'react'." }, + Only_amd_and_system_modules_are_supported_alongside_0: { code: 6082, category: ts.DiagnosticCategory.Error, key: "Only_amd_and_system_modules_are_supported_alongside_0_6082", message: "Only 'amd' and 'system' modules are supported alongside --{0}." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -3173,7 +3178,7 @@ var ts; function getCommentRanges(text, pos, trailing) { var result; var collecting = trailing || pos === 0; - while (true) { + while (pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13 /* carriageReturn */: @@ -3242,6 +3247,7 @@ var ts; } return result; } + return result; } function getLeadingCommentRanges(text, pos) { return getCommentRanges(text, pos, /*trailing*/ false); @@ -3343,7 +3349,7 @@ var ts; error(ts.Diagnostics.Digit_expected); } } - return +(text.substring(start, end)); + return "" + +(text.substring(start, end)); } function scanOctalDigits() { var start = pos; @@ -3770,7 +3776,7 @@ var ts; return pos++, token = 36 /* MinusToken */; case 46 /* dot */: if (isDigit(text.charCodeAt(pos + 1))) { - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8 /* NumericLiteral */; } if (text.charCodeAt(pos + 1) === 46 /* dot */ && text.charCodeAt(pos + 2) === 46 /* dot */) { @@ -3873,7 +3879,7 @@ var ts; case 55 /* _7 */: case 56 /* _8 */: case 57 /* _9 */: - tokenValue = "" + scanNumber(); + tokenValue = scanNumber(); return token = 8 /* NumericLiteral */; case 58 /* colon */: return pos++, token = 54 /* ColonToken */; @@ -4177,1321 +4183,6 @@ var ts; } ts.createScanner = createScanner; })(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - ts.bindTime = 0; - (function (ModuleInstanceState) { - ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; - ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; - ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; - })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); - var ModuleInstanceState = ts.ModuleInstanceState; - var Reachability; - (function (Reachability) { - Reachability[Reachability["Unintialized"] = 1] = "Unintialized"; - Reachability[Reachability["Reachable"] = 2] = "Reachable"; - Reachability[Reachability["Unreachable"] = 4] = "Unreachable"; - Reachability[Reachability["ReportedUnreachable"] = 8] = "ReportedUnreachable"; - })(Reachability || (Reachability = {})); - function or(state1, state2) { - return (state1 | state2) & 2 /* Reachable */ - ? 2 /* Reachable */ - : (state1 & state2) & 8 /* ReportedUnreachable */ - ? 8 /* ReportedUnreachable */ - : 4 /* Unreachable */; - } - function getModuleInstanceState(node) { - // A module is uninstantiated if it contains only - // 1. interface declarations, type alias declarations - if (node.kind === 215 /* InterfaceDeclaration */ || node.kind === 216 /* TypeAliasDeclaration */) { - return 0 /* NonInstantiated */; - } - else if (ts.isConstEnumDeclaration(node)) { - return 2 /* ConstEnumOnly */; - } - else if ((node.kind === 222 /* ImportDeclaration */ || node.kind === 221 /* ImportEqualsDeclaration */) && !(node.flags & 2 /* Export */)) { - return 0 /* NonInstantiated */; - } - else if (node.kind === 219 /* ModuleBlock */) { - var state = 0 /* NonInstantiated */; - ts.forEachChild(node, function (n) { - switch (getModuleInstanceState(n)) { - case 0 /* NonInstantiated */: - // child is non-instantiated - continue searching - return false; - case 2 /* ConstEnumOnly */: - // child is const enum only - record state and continue searching - state = 2 /* ConstEnumOnly */; - return false; - case 1 /* Instantiated */: - // child is instantiated - record state and stop - state = 1 /* Instantiated */; - return true; - } - }); - return state; - } - else if (node.kind === 218 /* ModuleDeclaration */) { - return getModuleInstanceState(node.body); - } - else { - return 1 /* Instantiated */; - } - } - ts.getModuleInstanceState = getModuleInstanceState; - var ContainerFlags; - (function (ContainerFlags) { - // The current node is not a container, and no container manipulation should happen before - // recursing into it. - ContainerFlags[ContainerFlags["None"] = 0] = "None"; - // The current node is a container. It should be set as the current container (and block- - // container) before recursing into it. The current node does not have locals. Examples: - // - // Classes, ObjectLiterals, TypeLiterals, Interfaces... - ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; - // The current node is a block-scoped-container. It should be set as the current block- - // container before recursing into it. Examples: - // - // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... - ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; - ContainerFlags[ContainerFlags["HasLocals"] = 4] = "HasLocals"; - // If the current node is a container that also container that also contains locals. Examples: - // - // Functions, Methods, Modules, Source-files. - ContainerFlags[ContainerFlags["IsContainerWithLocals"] = 5] = "IsContainerWithLocals"; - })(ContainerFlags || (ContainerFlags = {})); - var binder = createBinder(); - function bindSourceFile(file, options) { - var start = new Date().getTime(); - binder(file, options); - ts.bindTime += new Date().getTime() - start; - } - ts.bindSourceFile = bindSourceFile; - function createBinder() { - var file; - var options; - var parent; - var container; - var blockScopeContainer; - var lastContainer; - var seenThisKeyword; - // state used by reachability checks - var hasExplicitReturn; - var currentReachabilityState; - var labelStack; - var labelIndexMap; - var implicitLabels; - // If this file is an external module, then it is automatically in strict-mode according to - // ES6. If it is not an external module, then we'll determine if it is in strict mode or - // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). - var inStrictMode; - var symbolCount = 0; - var Symbol; - var classifiableNames; - function bindSourceFile(f, opts) { - file = f; - options = opts; - inStrictMode = !!file.externalModuleIndicator; - classifiableNames = {}; - Symbol = ts.objectAllocator.getSymbolConstructor(); - if (!file.locals) { - bind(file); - file.symbolCount = symbolCount; - file.classifiableNames = classifiableNames; - } - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - seenThisKeyword = false; - hasExplicitReturn = false; - labelStack = undefined; - labelIndexMap = undefined; - implicitLabels = undefined; - } - return bindSourceFile; - function createSymbol(flags, name) { - symbolCount++; - return new Symbol(flags, name); - } - function addDeclarationToSymbol(symbol, node, symbolFlags) { - symbol.flags |= symbolFlags; - node.symbol = symbol; - if (!symbol.declarations) { - symbol.declarations = []; - } - symbol.declarations.push(node); - if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { - symbol.exports = {}; - } - if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { - symbol.members = {}; - } - if (symbolFlags & 107455 /* Value */ && !symbol.valueDeclaration) { - symbol.valueDeclaration = node; - } - } - // Should not be called on a declaration with a computed property name, - // unless it is a well known Symbol. - function getDeclarationName(node) { - if (node.name) { - if (node.kind === 218 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */) { - return "\"" + node.name.text + "\""; - } - if (node.name.kind === 136 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); - return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); - } - return node.name.text; - } - switch (node.kind) { - case 144 /* Constructor */: - return "__constructor"; - case 152 /* FunctionType */: - case 147 /* CallSignature */: - return "__call"; - case 153 /* ConstructorType */: - case 148 /* ConstructSignature */: - return "__new"; - case 149 /* IndexSignature */: - return "__index"; - case 228 /* ExportDeclaration */: - return "__export"; - case 227 /* ExportAssignment */: - return node.isExportEquals ? "export=" : "default"; - case 213 /* FunctionDeclaration */: - case 214 /* ClassDeclaration */: - return node.flags & 512 /* Default */ ? "default" : undefined; - } - } - function getDisplayName(node) { - return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); - } - /** - * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. - * @param symbolTable - The symbol table which node will be added to. - * @param parent - node's parent declaration. - * @param node - The declaration to be added to the symbol table - * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) - * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. - */ - function declareSymbol(symbolTable, parent, node, includes, excludes) { - ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = node.flags & 512 /* Default */; - // The exported symbol for an export default function/class node is always named "default" - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); - var symbol; - if (name !== undefined) { - // Check and see if the symbol table already has a symbol with this name. If not, - // create a new symbol with this name and add it to the table. Note that we don't - // give the new symbol any flags *yet*. This ensures that it will not conflict - // with the 'excludes' flags we pass in. - // - // If we do get an existing symbol, see if it conflicts with the new symbol we're - // creating. For example, a 'var' symbol and a 'class' symbol will conflict within - // the same symbol table. If we have a conflict, report the issue on each - // declaration we have for this symbol, and then create a new symbol for this - // declaration. - // - // If we created a new symbol, either because we didn't have a symbol with this name - // in the symbol table, or we conflicted with an existing symbol, then just add this - // node as the sole declaration of the new symbol. - // - // Otherwise, we'll be merging into a compatible existing symbol (for example when - // you have multiple 'vars' with the same name in the same container). In this case - // just add this node into the declarations list of the symbol. - symbol = ts.hasProperty(symbolTable, name) - ? symbolTable[name] - : (symbolTable[name] = createSymbol(0 /* None */, name)); - if (name && (includes & 788448 /* Classifiable */)) { - classifiableNames[name] = name; - } - if (symbol.flags & excludes) { - if (node.name) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration - // Report errors on previous encountered declarations - var message = symbol.flags & 2 /* BlockScopedVariable */ - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.flags & 512 /* Default */) { - message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); - ts.forEach(symbol.declarations, function (declaration) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); - }); - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); - symbol = createSymbol(0 /* None */, name); - } - } - else { - symbol = createSymbol(0 /* None */, "__missing"); - } - addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; - return symbol; - } - function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedNodeFlags(node) & 2 /* Export */; - if (symbolFlags & 8388608 /* Alias */) { - if (node.kind === 230 /* ExportSpecifier */ || (node.kind === 221 /* ImportEqualsDeclaration */ && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - else { - // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, - // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set - // on it. There are 2 main reasons: - // - // 1. We treat locals and exports of the same name as mutually exclusive within a container. - // That means the binder will issue a Duplicate Identifier error if you mix locals and exports - // with the same name in the same container. - // TODO: Make this a more specific error and decouple it from the exclusion logic. - // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, - // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way - // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. - if (hasExportModifier || container.flags & 131072 /* ExportContext */) { - var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | - (symbolFlags & 793056 /* Type */ ? 2097152 /* ExportType */ : 0) | - (symbolFlags & 1536 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - node.localSymbol = local; - return local; - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - } - // All container nodes are kept on a linked list in declaration order. This list is used by - // the getLocalNameOfContainer function in the type checker to validate that the local name - // used for a container is unique. - function bindChildren(node) { - // Before we recurse into a node's chilren, we first save the existing parent, container - // and block-container. Then after we pop out of processing the children, we restore - // these saved values. - var saveParent = parent; - var saveContainer = container; - var savedBlockScopeContainer = blockScopeContainer; - // This node will now be set as the parent of all of its children as we recurse into them. - parent = node; - // Depending on what kind of node this is, we may have to adjust the current container - // and block-container. If the current node is a container, then it is automatically - // considered the current block-container as well. Also, for containers that we know - // may contain locals, we proactively initialize the .locals field. We do this because - // it's highly likely that the .locals will be needed to place some child in (for example, - // a parameter, or variable declaration). - // - // However, we do not proactively create the .locals for block-containers because it's - // totally normal and common for block-containers to never actually have a block-scoped - // variable in them. We don't want to end up allocating an object for every 'block' we - // run into when most of them won't be necessary. - // - // Finally, if this is a block-container, then we clear out any existing .locals object - // it may contain within it. This happens in incremental scenarios. Because we can be - // reusing a node from a previous compilation, that node may have had 'locals' created - // for it. We must clear this so we don't accidently move any stale data forward from - // a previous compilation. - var containerFlags = getContainerFlags(node); - if (containerFlags & 1 /* IsContainer */) { - container = blockScopeContainer = node; - if (containerFlags & 4 /* HasLocals */) { - container.locals = {}; - } - addToContainerChain(container); - } - else if (containerFlags & 2 /* IsBlockScopedContainer */) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; - } - var savedReachabilityState; - var savedLabelStack; - var savedLabels; - var savedImplicitLabels; - var savedHasExplicitReturn; - var kind = node.kind; - var flags = node.flags; - // reset all reachability check related flags on node (for incremental scenarios) - flags &= ~1572864 /* ReachabilityCheckFlags */; - if (kind === 215 /* InterfaceDeclaration */) { - seenThisKeyword = false; - } - var saveState = kind === 248 /* SourceFile */ || kind === 219 /* ModuleBlock */ || ts.isFunctionLikeKind(kind); - if (saveState) { - savedReachabilityState = currentReachabilityState; - savedLabelStack = labelStack; - savedLabels = labelIndexMap; - savedImplicitLabels = implicitLabels; - savedHasExplicitReturn = hasExplicitReturn; - currentReachabilityState = 2 /* Reachable */; - hasExplicitReturn = false; - labelStack = labelIndexMap = implicitLabels = undefined; - } - bindReachableStatement(node); - if (currentReachabilityState === 2 /* Reachable */ && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { - flags |= 524288 /* HasImplicitReturn */; - if (hasExplicitReturn) { - flags |= 1048576 /* HasExplicitReturn */; - } - } - if (kind === 215 /* InterfaceDeclaration */) { - flags = seenThisKeyword ? flags | 262144 /* ContainsThis */ : flags & ~262144 /* ContainsThis */; - } - node.flags = flags; - if (saveState) { - hasExplicitReturn = savedHasExplicitReturn; - currentReachabilityState = savedReachabilityState; - labelStack = savedLabelStack; - labelIndexMap = savedLabels; - implicitLabels = savedImplicitLabels; - } - container = saveContainer; - parent = saveParent; - blockScopeContainer = savedBlockScopeContainer; - } - /** - * Returns true if node and its subnodes were successfully traversed. - * Returning false means that node was not examined and caller needs to dive into the node himself. - */ - function bindReachableStatement(node) { - if (checkUnreachable(node)) { - ts.forEachChild(node, bind); - return; - } - switch (node.kind) { - case 198 /* WhileStatement */: - bindWhileStatement(node); - break; - case 197 /* DoStatement */: - bindDoStatement(node); - break; - case 199 /* ForStatement */: - bindForStatement(node); - break; - case 200 /* ForInStatement */: - case 201 /* ForOfStatement */: - bindForInOrForOfStatement(node); - break; - case 196 /* IfStatement */: - bindIfStatement(node); - break; - case 204 /* ReturnStatement */: - case 208 /* ThrowStatement */: - bindReturnOrThrow(node); - break; - case 203 /* BreakStatement */: - case 202 /* ContinueStatement */: - bindBreakOrContinueStatement(node); - break; - case 209 /* TryStatement */: - bindTryStatement(node); - break; - case 206 /* SwitchStatement */: - bindSwitchStatement(node); - break; - case 220 /* CaseBlock */: - bindCaseBlock(node); - break; - case 207 /* LabeledStatement */: - bindLabeledStatement(node); - break; - default: - ts.forEachChild(node, bind); - break; - } - } - function bindWhileStatement(n) { - var preWhileState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - var postWhileState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - // bind expressions (don't affect reachability) - bind(n.expression); - currentReachabilityState = preWhileState; - var postWhileLabel = pushImplicitLabel(); - bind(n.statement); - popImplicitLabel(postWhileLabel, postWhileState); - } - function bindDoStatement(n) { - var preDoState = currentReachabilityState; - var postDoLabel = pushImplicitLabel(); - bind(n.statement); - var postDoState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : preDoState; - popImplicitLabel(postDoLabel, postDoState); - // bind expressions (don't affect reachability) - bind(n.expression); - } - function bindForStatement(n) { - var preForState = currentReachabilityState; - var postForLabel = pushImplicitLabel(); - // bind expressions (don't affect reachability) - bind(n.initializer); - bind(n.condition); - bind(n.incrementor); - bind(n.statement); - // for statement is considered infinite when it condition is either omitted or is true keyword - // - for(..;;..) - // - for(..;true;..) - var isInfiniteLoop = (!n.condition || n.condition.kind === 99 /* TrueKeyword */); - var postForState = isInfiniteLoop ? 4 /* Unreachable */ : preForState; - popImplicitLabel(postForLabel, postForState); - } - function bindForInOrForOfStatement(n) { - var preStatementState = currentReachabilityState; - var postStatementLabel = pushImplicitLabel(); - // bind expressions (don't affect reachability) - bind(n.initializer); - bind(n.expression); - bind(n.statement); - popImplicitLabel(postStatementLabel, preStatementState); - } - function bindIfStatement(n) { - // denotes reachability state when entering 'thenStatement' part of the if statement: - // i.e. if condition is false then thenStatement is unreachable - var ifTrueState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - // denotes reachability state when entering 'elseStatement': - // i.e. if condition is true then elseStatement is unreachable - var ifFalseState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; - currentReachabilityState = ifTrueState; - // bind expression (don't affect reachability) - bind(n.expression); - bind(n.thenStatement); - if (n.elseStatement) { - var preElseState = currentReachabilityState; - currentReachabilityState = ifFalseState; - bind(n.elseStatement); - currentReachabilityState = or(currentReachabilityState, preElseState); - } - else { - currentReachabilityState = or(currentReachabilityState, ifFalseState); - } - } - function bindReturnOrThrow(n) { - // bind expression (don't affect reachability) - bind(n.expression); - if (n.kind === 204 /* ReturnStatement */) { - hasExplicitReturn = true; - } - currentReachabilityState = 4 /* Unreachable */; - } - function bindBreakOrContinueStatement(n) { - // call bind on label (don't affect reachability) - bind(n.label); - // for continue case touch label so it will be marked a used - var isValidJump = jumpToLabel(n.label, n.kind === 203 /* BreakStatement */ ? currentReachabilityState : 4 /* Unreachable */); - if (isValidJump) { - currentReachabilityState = 4 /* Unreachable */; - } - } - function bindTryStatement(n) { - // catch\finally blocks has the same reachability as try block - var preTryState = currentReachabilityState; - bind(n.tryBlock); - var postTryState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.catchClause); - var postCatchState = currentReachabilityState; - currentReachabilityState = preTryState; - bind(n.finallyBlock); - // post catch/finally state is reachable if - // - post try state is reachable - control flow can fall out of try block - // - post catch state is reachable - control flow can fall out of catch block - currentReachabilityState = or(postTryState, postCatchState); - } - function bindSwitchStatement(n) { - var preSwitchState = currentReachabilityState; - var postSwitchLabel = pushImplicitLabel(); - // bind expression (don't affect reachability) - bind(n.expression); - bind(n.caseBlock); - var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242 /* DefaultClause */; }); - // post switch state is unreachable if switch is exaustive (has a default case ) and does not have fallthrough from the last case - var postSwitchState = hasDefault && currentReachabilityState !== 2 /* Reachable */ ? 4 /* Unreachable */ : preSwitchState; - popImplicitLabel(postSwitchLabel, postSwitchState); - } - function bindCaseBlock(n) { - var startState = currentReachabilityState; - for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { - var clause = _a[_i]; - currentReachabilityState = startState; - bind(clause); - if (clause.statements.length && currentReachabilityState === 2 /* Reachable */ && options.noFallthroughCasesInSwitch) { - errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); - } - } - } - function bindLabeledStatement(n) { - // call bind on label (don't affect reachability) - bind(n.label); - var ok = pushNamedLabel(n.label); - bind(n.statement); - if (ok) { - popNamedLabel(n.label, currentReachabilityState); - } - } - function getContainerFlags(node) { - switch (node.kind) { - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - case 215 /* InterfaceDeclaration */: - case 217 /* EnumDeclaration */: - case 155 /* TypeLiteral */: - case 165 /* ObjectLiteralExpression */: - return 1 /* IsContainer */; - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - case 213 /* FunctionDeclaration */: - case 144 /* Constructor */: - case 145 /* GetAccessor */: - case 146 /* SetAccessor */: - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - case 218 /* ModuleDeclaration */: - case 248 /* SourceFile */: - case 216 /* TypeAliasDeclaration */: - return 5 /* IsContainerWithLocals */; - case 244 /* CatchClause */: - case 199 /* ForStatement */: - case 200 /* ForInStatement */: - case 201 /* ForOfStatement */: - case 220 /* CaseBlock */: - return 2 /* IsBlockScopedContainer */; - case 192 /* Block */: - // do not treat blocks directly inside a function as a block-scoped-container. - // Locals that reside in this block should go to the function locals. Othewise 'x' - // would not appear to be a redeclaration of a block scoped local in the following - // example: - // - // function foo() { - // var x; - // let x; - // } - // - // If we placed 'var x' into the function locals and 'let x' into the locals of - // the block, then there would be no collision. - // - // By not creating a new block-scoped-container here, we ensure that both 'var x' - // and 'let x' go into the Function-container's locals, and we do get a collision - // conflict. - return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; - } - return 0 /* None */; - } - function addToContainerChain(next) { - if (lastContainer) { - lastContainer.nextContainer = next; - } - lastContainer = next; - } - function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { - // Just call this directly so that the return type of this function stays "void". - declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); - } - function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { - switch (container.kind) { - // Modules, source files, and classes need specialized handling for how their - // members are declared (for example, a member of a class will go into a specific - // symbol table depending on if it is static or not). We defer to specialized - // handlers to take care of declaring these child members. - case 218 /* ModuleDeclaration */: - return declareModuleMember(node, symbolFlags, symbolExcludes); - case 248 /* SourceFile */: - return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - return declareClassMember(node, symbolFlags, symbolExcludes); - case 217 /* EnumDeclaration */: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 155 /* TypeLiteral */: - case 165 /* ObjectLiteralExpression */: - case 215 /* InterfaceDeclaration */: - // Interface/Object-types always have their children added to the 'members' of - // their container. They are only accessible through an instance of their - // container, and are never in scope otherwise (even inside the body of the - // object / type / interface declaring them). An exception is type parameters, - // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - case 144 /* Constructor */: - case 145 /* GetAccessor */: - case 146 /* SetAccessor */: - case 213 /* FunctionDeclaration */: - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - case 216 /* TypeAliasDeclaration */: - // All the children of these container types are never visible through another - // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, - // they're only accessed 'lexically' (i.e. from code that exists underneath - // their container in the tree. To accomplish this, we simply add their declared - // symbol to the 'locals' of the container. These symbols can then be found as - // the type checker walks up the containers, checking them for matching names. - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function declareClassMember(node, symbolFlags, symbolExcludes) { - return node.flags & 64 /* Static */ - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - } - function declareSourceFileMember(node, symbolFlags, symbolExcludes) { - return ts.isExternalModule(file) - ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); - } - function hasExportDeclarations(node) { - var body = node.kind === 248 /* SourceFile */ ? node : node.body; - if (body.kind === 248 /* SourceFile */ || body.kind === 219 /* ModuleBlock */) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var stat = _a[_i]; - if (stat.kind === 228 /* ExportDeclaration */ || stat.kind === 227 /* ExportAssignment */) { - return true; - } - } - } - return false; - } - function setExportContextFlag(node) { - // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular - // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { - node.flags |= 131072 /* ExportContext */; - } - else { - node.flags &= ~131072 /* ExportContext */; - } - } - function bindModuleDeclaration(node) { - setExportContextFlag(node); - if (node.name.kind === 9 /* StringLiteral */) { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - } - else { - var state = getModuleInstanceState(node); - if (state === 0 /* NonInstantiated */) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); - } - else { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { - // if module was already merged with some function, class or non-const enum - // treat is a non-const-enum-only - node.symbol.constEnumOnlyModule = false; - } - else { - var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; - if (node.symbol.constEnumOnlyModule === undefined) { - // non-merged case - use the current state - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - // merged case: module is const enum only if all its pieces are non-instantiated or const enum - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } - } - } - } - function bindFunctionOrConstructorType(node) { - // For a given function symbol "<...>(...) => T" we want to generate a symbol identical - // to the one we would get for: { <...>(...): T } - // - // We do that by making an anonymous type literal symbol, and then setting the function - // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable - // from an actual type literal symbol you would have gotten had you used the long form. - var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072 /* Signature */); - var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); - typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); - var _a; - } - function bindObjectLiteralExpression(node) { - var ElementKind; - (function (ElementKind) { - ElementKind[ElementKind["Property"] = 1] = "Property"; - ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; - })(ElementKind || (ElementKind = {})); - if (inStrictMode) { - var seen = {}; - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - if (prop.name.kind !== 69 /* Identifier */) { - continue; - } - var identifier = prop.name; - // ECMA-262 11.1.5 Object Initialiser - // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true - // a.This production is contained in strict code and IsDataDescriptor(previous) is true and - // IsDataDescriptor(propId.descriptor) is true. - // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. - // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. - // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true - // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields - var currentKind = prop.kind === 245 /* PropertyAssignment */ || prop.kind === 246 /* ShorthandPropertyAssignment */ || prop.kind === 143 /* MethodDeclaration */ - ? 1 /* Property */ - : 2 /* Accessor */; - var existingKind = seen[identifier.text]; - if (!existingKind) { - seen[identifier.text] = currentKind; - continue; - } - if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { - var span = ts.getErrorSpanForNode(file, identifier); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); - } - } - } - return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); - } - function bindAnonymousDeclaration(node, symbolFlags, name) { - var symbol = createSymbol(symbolFlags, name); - addDeclarationToSymbol(symbol, node, symbolFlags); - } - function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { - switch (blockScopeContainer.kind) { - case 218 /* ModuleDeclaration */: - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - case 248 /* SourceFile */: - if (ts.isExternalModule(container)) { - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - } - // fall through. - default: - if (!blockScopeContainer.locals) { - blockScopeContainer.locals = {}; - addToContainerChain(blockScopeContainer); - } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); - } - // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized - // check for reserved words used as identifiers in strict mode code. - function checkStrictModeIdentifier(node) { - if (inStrictMode && - node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && - node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && - !ts.isIdentifierName(node)) { - // Report error only if there are no parse errors in file - if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); - } - } - } - function getStrictModeIdentifierMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; - } - function checkStrictModeBinaryExpression(node) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { - // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkStrictModeEvalOrArguments(node, node.left); - } - } - function checkStrictModeCatchClause(node) { - // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the - // Catch production is eval or arguments - if (inStrictMode && node.variableDeclaration) { - checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); - } - } - function checkStrictModeDeleteExpression(node) { - // Grammar checking - if (inStrictMode && node.expression.kind === 69 /* Identifier */) { - // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its - // UnaryExpression is a direct reference to a variable, function argument, or function name - var span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); - } - } - function isEvalOrArgumentsIdentifier(node) { - return node.kind === 69 /* Identifier */ && - (node.text === "eval" || node.text === "arguments"); - } - function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 69 /* Identifier */) { - var identifier = name; - if (isEvalOrArgumentsIdentifier(identifier)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); - } - } - } - function getStrictModeEvalOrArgumentsMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; - } - function checkStrictModeFunctionName(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) - checkStrictModeEvalOrArguments(node, node.name); - } - } - function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.flags & 32768 /* OctalLiteral */) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); - } - } - function checkStrictModePostfixUnaryExpression(node) { - // Grammar checking - // The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression - // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - function checkStrictModePrefixUnaryExpression(node) { - // Grammar checking - if (inStrictMode) { - if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - } - function checkStrictModeWithStatement(node) { - // Grammar checking for withStatement - if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); - } - } - function errorOnFirstToken(node, message, arg0, arg1, arg2) { - var span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); - } - function getDestructuringParameterName(node) { - return "__" + ts.indexOf(node.parent.parameters, node); - } - function bind(node) { - if (!node) { - return; - } - node.parent = parent; - var savedInStrictMode = inStrictMode; - if (!savedInStrictMode) { - updateStrictMode(node); - } - // First we bind declaration nodes to a symbol if possible. We'll both create a symbol - // and then potentially add the symbol to an appropriate symbol table. Possible - // destination symbol tables are: - // - // 1) The 'exports' table of the current container's symbol. - // 2) The 'members' table of the current container's symbol. - // 3) The 'locals' table of the current container. - // - // However, not all symbols will end up in any of these tables. 'Anonymous' symbols - // (like TypeLiterals for example) will not be put in any table. - bindWorker(node); - // Then we recurse into the children of the node to bind them as well. For certain - // symbols we do specialized work when we recurse. For example, we'll keep track of - // the current 'container' node when it changes. This helps us know which symbol table - // a local should go into for example. - bindChildren(node); - inStrictMode = savedInStrictMode; - } - function updateStrictMode(node) { - switch (node.kind) { - case 248 /* SourceFile */: - case 219 /* ModuleBlock */: - updateStrictModeStatementList(node.statements); - return; - case 192 /* Block */: - if (ts.isFunctionLike(node.parent)) { - updateStrictModeStatementList(node.statements); - } - return; - case 214 /* ClassDeclaration */: - case 186 /* ClassExpression */: - // All classes are automatically in strict mode in ES6. - inStrictMode = true; - return; - } - } - function updateStrictModeStatementList(statements) { - for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { - var statement = statements_1[_i]; - if (!ts.isPrologueDirective(statement)) { - return; - } - if (isUseStrictPrologueDirective(statement)) { - inStrictMode = true; - return; - } - } - } - /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node) { - var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); - // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the - // string to contain unicode escapes (as per ES5). - return nodeText === "\"use strict\"" || nodeText === "'use strict'"; - } - function bindWorker(node) { - switch (node.kind) { - case 69 /* Identifier */: - return checkStrictModeIdentifier(node); - case 181 /* BinaryExpression */: - return checkStrictModeBinaryExpression(node); - case 244 /* CatchClause */: - return checkStrictModeCatchClause(node); - case 175 /* DeleteExpression */: - return checkStrictModeDeleteExpression(node); - case 8 /* NumericLiteral */: - return checkStrictModeNumericLiteral(node); - case 180 /* PostfixUnaryExpression */: - return checkStrictModePostfixUnaryExpression(node); - case 179 /* PrefixUnaryExpression */: - return checkStrictModePrefixUnaryExpression(node); - case 205 /* WithStatement */: - return checkStrictModeWithStatement(node); - case 97 /* ThisKeyword */: - seenThisKeyword = true; - return; - case 137 /* TypeParameter */: - return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530912 /* TypeParameterExcludes */); - case 138 /* Parameter */: - return bindParameter(node); - case 211 /* VariableDeclaration */: - case 163 /* BindingElement */: - return bindVariableDeclarationOrBindingElement(node); - case 141 /* PropertyDeclaration */: - case 140 /* PropertySignature */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 107455 /* PropertyExcludes */); - case 245 /* PropertyAssignment */: - case 246 /* ShorthandPropertyAssignment */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 107455 /* PropertyExcludes */); - case 247 /* EnumMember */: - return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 107455 /* EnumMemberExcludes */); - case 147 /* CallSignature */: - case 148 /* ConstructSignature */: - case 149 /* IndexSignature */: - return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); - case 143 /* MethodDeclaration */: - case 142 /* MethodSignature */: - // If this is an ObjectLiteralExpression method, then it sits in the same space - // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes - // so that it will conflict with any other object literal members with the same - // name. - return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 107455 /* PropertyExcludes */ : 99263 /* MethodExcludes */); - case 213 /* FunctionDeclaration */: - checkStrictModeFunctionName(node); - return declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); - case 144 /* Constructor */: - return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); - case 145 /* GetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); - case 146 /* SetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); - case 152 /* FunctionType */: - case 153 /* ConstructorType */: - return bindFunctionOrConstructorType(node); - case 155 /* TypeLiteral */: - return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); - case 165 /* ObjectLiteralExpression */: - return bindObjectLiteralExpression(node); - case 173 /* FunctionExpression */: - case 174 /* ArrowFunction */: - checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.text : "__function"; - return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); - case 186 /* ClassExpression */: - case 214 /* ClassDeclaration */: - return bindClassLikeDeclaration(node); - case 215 /* InterfaceDeclaration */: - return bindBlockScopedDeclaration(node, 64 /* Interface */, 792960 /* InterfaceExcludes */); - case 216 /* TypeAliasDeclaration */: - return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793056 /* TypeAliasExcludes */); - case 217 /* EnumDeclaration */: - return bindEnumDeclaration(node); - case 218 /* ModuleDeclaration */: - return bindModuleDeclaration(node); - case 221 /* ImportEqualsDeclaration */: - case 224 /* NamespaceImport */: - case 226 /* ImportSpecifier */: - case 230 /* ExportSpecifier */: - return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - case 223 /* ImportClause */: - return bindImportClause(node); - case 228 /* ExportDeclaration */: - return bindExportDeclaration(node); - case 227 /* ExportAssignment */: - return bindExportAssignment(node); - case 248 /* SourceFile */: - return bindSourceFileIfExternalModule(); - } - } - function bindSourceFileIfExternalModule() { - setExportContextFlag(file); - if (ts.isExternalModule(file)) { - bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); - } - } - function bindExportAssignment(node) { - if (!container.symbol || !container.symbol.exports) { - // Export assignment in some sort of block construct - bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); - } - else if (node.expression.kind === 69 /* Identifier */) { - // An export default clause with an identifier exports all meanings of that identifier - declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* Alias */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); - } - else { - // An export default clause with an expression exports a value - declareSymbol(container.symbol.exports, container.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); - } - } - function bindExportDeclaration(node) { - if (!container.symbol || !container.symbol.exports) { - // Export * in some sort of block construct - bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); - } - else if (!node.exportClause) { - // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); - } - } - function bindImportClause(node) { - if (node.name) { - declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - } - } - function bindClassLikeDeclaration(node) { - if (node.kind === 214 /* ClassDeclaration */) { - bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); - } - else { - var bindingName = node.name ? node.name.text : "__class"; - bindAnonymousDeclaration(node, 32 /* Class */, bindingName); - // Add name of class expression into the map for semantic classifier - if (node.name) { - classifiableNames[node.name.text] = node.name.text; - } - } - var symbol = node.symbol; - // TypeScript 1.0 spec (April 2014): 8.4 - // Every class automatically contains a static property member named 'prototype', the - // type of which is an instantiation of the class type with type Any supplied as a type - // argument for each type parameter. It is an error to explicitly declare a static - // property member with the name 'prototype'. - // - // Note: we check for this here because this class may be merging into a module. The - // module might have an exported variable called 'prototype'. We can't allow that as - // that would clash with the built-in 'prototype' for the class. - var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); - if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { - if (node.name) { - node.name.parent = node; - } - file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); - } - symbol.exports[prototypeSymbol.name] = prototypeSymbol; - prototypeSymbol.parent = symbol; - } - function bindEnumDeclaration(node) { - return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) - : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); - } - function bindVariableDeclarationOrBindingElement(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); - } - if (!ts.isBindingPattern(node.name)) { - if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); - } - else if (ts.isParameterDeclaration(node)) { - // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration - // because its parent chain has already been set up, since parents are set before descending into children. - // - // If node is a binding element in parameter declaration, we need to use ParameterExcludes. - // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration - // For example: - // function foo([a,a]) {} // Duplicate Identifier error - // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter - // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); - } - } - } - function bindParameter(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a - // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) - checkStrictModeEvalOrArguments(node, node.name); - } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); - } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - // If this is a property-parameter, then also declare the property symbol into the - // containing class. - if (node.flags & 56 /* AccessibilityModifier */ && - node.parent.kind === 144 /* Constructor */ && - ts.isClassLike(node.parent.parent)) { - var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */); - } - } - function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") - : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); - } - // reachability checks - function pushNamedLabel(name) { - initializeReachabilityStateIfNecessary(); - if (ts.hasProperty(labelIndexMap, name.text)) { - return false; - } - labelIndexMap[name.text] = labelStack.push(1 /* Unintialized */) - 1; - return true; - } - function pushImplicitLabel() { - initializeReachabilityStateIfNecessary(); - var index = labelStack.push(1 /* Unintialized */) - 1; - implicitLabels.push(index); - return index; - } - function popNamedLabel(label, outerState) { - var index = labelIndexMap[label.text]; - ts.Debug.assert(index !== undefined); - ts.Debug.assert(labelStack.length == index + 1); - labelIndexMap[label.text] = undefined; - setCurrentStateAtLabel(labelStack.pop(), outerState, label); - } - function popImplicitLabel(implicitLabelIndex, outerState) { - if (labelStack.length !== implicitLabelIndex + 1) { - ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); - } - var i = implicitLabels.pop(); - if (implicitLabelIndex !== i) { - ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); - } - setCurrentStateAtLabel(labelStack.pop(), outerState, /*name*/ undefined); - } - function setCurrentStateAtLabel(innerMergedState, outerState, label) { - if (innerMergedState === 1 /* Unintialized */) { - if (label && !options.allowUnusedLabels) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); - } - currentReachabilityState = outerState; - } - else { - currentReachabilityState = or(innerMergedState, outerState); - } - } - function jumpToLabel(label, outerState) { - initializeReachabilityStateIfNecessary(); - var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); - if (index === undefined) { - // reference to unknown label or - // break/continue used outside of loops - return false; - } - var stateAtLabel = labelStack[index]; - labelStack[index] = stateAtLabel === 1 /* Unintialized */ ? outerState : or(stateAtLabel, outerState); - return true; - } - function checkUnreachable(node) { - switch (currentReachabilityState) { - case 4 /* Unreachable */: - var reportError = - // report error on all statements - ts.isStatement(node) || - // report error on class declarations - node.kind === 214 /* ClassDeclaration */ || - // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === 218 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || - // report error on regular enums and const enums if preserveConstEnums is set - (node.kind === 217 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); - if (reportError) { - currentReachabilityState = 8 /* ReportedUnreachable */; - // unreachable code is reported if - // - user has explicitly asked about it AND - // - statement is in not ambient context (statements in ambient context is already an error - // so we should not report extras) AND - // - node is not variable statement OR - // - node is block scoped variable statement OR - // - node is not block scoped variable statement and at least one variable declaration has initializer - // Rationale: we don't want to report errors on non-initialized var's since they are hoisted - // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - var reportUnreachableCode = !options.allowUnreachableCode && - !ts.isInAmbientContext(node) && - (node.kind !== 193 /* VariableStatement */ || - ts.getCombinedNodeFlags(node.declarationList) & 24576 /* BlockScoped */ || - ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); - if (reportUnreachableCode) { - errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); - } - } - case 8 /* ReportedUnreachable */: - return true; - default: - return false; - } - function shouldReportErrorOnModuleDeclaration(node) { - var instanceState = getModuleInstanceState(node); - return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); - } - } - function initializeReachabilityStateIfNecessary() { - if (labelIndexMap) { - return; - } - currentReachabilityState = 2 /* Reachable */; - labelIndexMap = {}; - labelStack = []; - implicitLabels = []; - } - } -})(ts || (ts = {})); -/// /// /* @internal */ var ts; @@ -5812,6 +4503,10 @@ var ts; return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + function isExternalOrCommonJsModule(file) { + return (file.externalModuleIndicator || file.commonJsModuleIndicator) !== undefined; + } + ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isDeclarationFile(file) { return (file.flags & 4096 /* DeclarationFile */) !== 0; } @@ -5865,19 +4560,27 @@ var ts; return ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; + function getLeadingCommentRangesOfNodeFromText(node, text) { + return ts.getLeadingCommentRanges(text, node.pos); + } + ts.getLeadingCommentRangesOfNodeFromText = getLeadingCommentRangesOfNodeFromText; function getJsDocComments(node, sourceFileOfNode) { + return getJsDocCommentsFromText(node, sourceFileOfNode.text); + } + ts.getJsDocComments = getJsDocComments; + function getJsDocCommentsFromText(node, text) { var commentRanges = (node.kind === 138 /* Parameter */ || node.kind === 137 /* TypeParameter */) ? - ts.concatenate(ts.getTrailingCommentRanges(sourceFileOfNode.text, node.pos), ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : - getLeadingCommentRangesOfNode(node, sourceFileOfNode); + ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : + getLeadingCommentRangesOfNodeFromText(node, text); return ts.filter(commentRanges, isJsDocComment); function isJsDocComment(comment) { // True if the comment starts with '/**' but not if it is '/**/' - return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && - sourceFileOfNode.text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && - sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== 47 /* slash */; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 3) !== 47 /* slash */; } } - ts.getJsDocComments = getJsDocComments; + ts.getJsDocCommentsFromText = getJsDocCommentsFromText; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; function isTypeNode(node) { @@ -6464,6 +5167,57 @@ var ts; return node.kind === 221 /* ImportEqualsDeclaration */ && node.moduleReference.kind !== 232 /* ExternalModuleReference */; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; + function isSourceFileJavaScript(file) { + return isInJavaScriptFile(file); + } + ts.isSourceFileJavaScript = isSourceFileJavaScript; + function isInJavaScriptFile(node) { + return node && !!(node.parserContextFlags & 32 /* JavaScriptFile */); + } + ts.isInJavaScriptFile = isInJavaScriptFile; + /** + * Returns true if the node is a CallExpression to the identifier 'require' with + * exactly one string literal argument. + * This function does not test if the node is in a JavaScript file or not. + */ + function isRequireCall(expression) { + // of the form 'require("name")' + return expression.kind === 168 /* CallExpression */ && + expression.expression.kind === 69 /* Identifier */ && + expression.expression.text === "require" && + expression.arguments.length === 1 && + expression.arguments[0].kind === 9 /* StringLiteral */; + } + ts.isRequireCall = isRequireCall; + /** + * Returns true if the node is an assignment to a property on the identifier 'exports'. + * This function does not test if the node is in a JavaScript file or not. + */ + function isExportsPropertyAssignment(expression) { + // of the form 'exports.name = expr' where 'name' and 'expr' are arbitrary + return isInJavaScriptFile(expression) && + (expression.kind === 181 /* BinaryExpression */) && + (expression.operatorToken.kind === 56 /* EqualsToken */) && + (expression.left.kind === 166 /* PropertyAccessExpression */) && + (expression.left.expression.kind === 69 /* Identifier */) && + ((expression.left.expression).text === "exports"); + } + ts.isExportsPropertyAssignment = isExportsPropertyAssignment; + /** + * Returns true if the node is an assignment to the property access expression 'module.exports'. + * This function does not test if the node is in a JavaScript file or not. + */ + function isModuleExportsAssignment(expression) { + // of the form 'module.exports = expr' where 'expr' is arbitrary + return isInJavaScriptFile(expression) && + (expression.kind === 181 /* BinaryExpression */) && + (expression.operatorToken.kind === 56 /* EqualsToken */) && + (expression.left.kind === 166 /* PropertyAccessExpression */) && + (expression.left.expression.kind === 69 /* Identifier */) && + ((expression.left.expression).text === "module") && + (expression.left.name.text === "exports"); + } + ts.isModuleExportsAssignment = isModuleExportsAssignment; function getExternalModuleName(node) { if (node.kind === 222 /* ImportDeclaration */) { return node.moduleSpecifier; @@ -6791,8 +5545,8 @@ var ts; function getFileReferenceFromReferencePath(comment, commentRange) { var simpleReferenceRegEx = /^\/\/\/\s*/gim; - if (simpleReferenceRegEx.exec(comment)) { - if (isNoDefaultLibRegEx.exec(comment)) { + if (simpleReferenceRegEx.test(comment)) { + if (isNoDefaultLibRegEx.test(comment)) { return { isNoDefaultLib: true }; @@ -6834,6 +5588,10 @@ var ts; return isFunctionLike(node) && (node.flags & 256 /* Async */) !== 0 && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; + function isStringOrNumericLiteral(kind) { + return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */; + } + ts.isStringOrNumericLiteral = isStringOrNumericLiteral; /** * A declaration has a dynamic name if both of the following are true: * 1. The declaration has a computed property name @@ -6842,11 +5600,15 @@ var ts; * Symbol. */ function hasDynamicName(declaration) { - return declaration.name && - declaration.name.kind === 136 /* ComputedPropertyName */ && - !isWellKnownSymbolSyntactically(declaration.name.expression); + return declaration.name && isDynamicName(declaration.name); } ts.hasDynamicName = hasDynamicName; + function isDynamicName(name) { + return name.kind === 136 /* ComputedPropertyName */ && + !isStringOrNumericLiteral(name.expression.kind) && + !isWellKnownSymbolSyntactically(name.expression); + } + ts.isDynamicName = isDynamicName; /** * Checks if the expression is of the form: * Symbol.name @@ -7087,11 +5849,11 @@ var ts; } ts.getIndentSize = getIndentSize; function createTextWriter(newLine) { - var output = ""; - var indent = 0; - var lineStart = true; - var lineCount = 0; - var linePos = 0; + var output; + var indent; + var lineStart; + var lineCount; + var linePos; function write(s) { if (s && s.length) { if (lineStart) { @@ -7101,6 +5863,13 @@ var ts; output += s; } } + function reset() { + output = ""; + indent = 0; + lineStart = true; + lineCount = 0; + linePos = 0; + } function rawWrite(s) { if (s !== undefined) { if (lineStart) { @@ -7127,9 +5896,10 @@ var ts; lineStart = true; } } - function writeTextOfNode(sourceFile, node) { - write(getSourceTextOfNodeFromSourceFile(sourceFile, node)); + function writeTextOfNode(text, node) { + write(getTextOfNodeFromSourceText(text, node)); } + reset(); return { write: write, rawWrite: rawWrite, @@ -7142,10 +5912,20 @@ var ts; getTextPos: function () { return output.length; }, getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, - getText: function () { return output; } + getText: function () { return output; }, + reset: reset }; } ts.createTextWriter = createTextWriter; + /** + * Resolves a local path to a path which is absolute to the base of the emit + */ + function getExternalModuleNameFromPath(host, fileName) { + var dir = host.getCurrentDirectory(); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, fileName, dir, function (f) { return host.getCanonicalFileName(f); }, /*isAbsolutePathAnUrl*/ false); + return ts.removeFileExtension(relativePath); + } + ts.getExternalModuleNameFromPath = getExternalModuleNameFromPath; function getOwnEmitOutputFilePath(sourceFile, host, extension) { var compilerOptions = host.getCompilerOptions(); var emitOutputFilePathWithoutExtension; @@ -7174,6 +5954,10 @@ var ts; return ts.getLineAndCharacterOfPosition(currentSourceFile, pos).line; } ts.getLineOfLocalPosition = getLineOfLocalPosition; + function getLineOfLocalPositionFromLineMap(lineMap, pos) { + return ts.computeLineAndCharacterOfPosition(lineMap, pos).line; + } + ts.getLineOfLocalPositionFromLineMap = getLineOfLocalPositionFromLineMap; function getFirstConstructorWithBody(node) { return ts.forEach(node.members, function (member) { if (member.kind === 144 /* Constructor */ && nodeIsPresent(member.body)) { @@ -7246,22 +6030,22 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; - function emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments) { + function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { // If the leading comments start on different line than the start of node, write new line if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) { + getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(currentSourceFile, writer, comments, trailingSeparator, newLine, writeComment) { + function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { var emitLeadingSpace = !trailingSeparator; ts.forEach(comments, function (comment) { if (emitLeadingSpace) { writer.write(" "); emitLeadingSpace = false; } - writeComment(currentSourceFile, writer, comment, newLine); + writeComment(text, lineMap, writer, comment, newLine); if (comment.hasTrailingNewLine) { writer.writeLine(); } @@ -7279,7 +6063,7 @@ var ts; * Detached comment is a comment at the top of file or function body that is separated from * the next statement by space. */ - function emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, removeComments) { + function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { @@ -7289,12 +6073,12 @@ var ts; // // var x = 10; if (node.pos === 0) { - leadingComments = ts.filter(ts.getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment); + leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedComment); } } else { // removeComments is false, just get detached as normal and bypass the process to filter comment - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { var detachedComments = []; @@ -7302,8 +6086,8 @@ var ts; for (var _i = 0, leadingComments_1 = leadingComments; _i < leadingComments_1.length; _i++) { var comment = leadingComments_1[_i]; if (lastComment) { - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end); - var commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); + var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { // There was a blank line between the last comment and this comment. This // comment is not part of the copyright comments. Return what we have so @@ -7318,36 +6102,36 @@ var ts; // All comments look like they could have been part of the copyright header. Make // sure there is at least one blank line between it and the node. If not, it's not // a copyright header. - var lastCommentLine = getLineOfLocalPosition(currentSourceFile, ts.lastOrUndefined(detachedComments).end); - var nodeLine = getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node.pos)); + var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.lastOrUndefined(detachedComments).end); + var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments - emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); - emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); + emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); + emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } } return currentDetachedCommentInfo; function isPinnedComment(comment) { - return currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 33 /* exclamation */; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 33 /* exclamation */; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(currentSourceFile, writer, comment, newLine) { - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { - var firstCommentLineAndCharacter = ts.getLineAndCharacterOfPosition(currentSourceFile, comment.pos); - var lineCount = ts.getLineStarts(currentSourceFile).length; + function writeCommentRange(text, lineMap, writer, comment, newLine) { + if (text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + var lineCount = lineMap.length; var firstCommentLineIndent; for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount - ? currentSourceFile.text.length + 1 - : getStartPositionOfLine(currentLine + 1, currentSourceFile); + ? text.length + 1 + : lineMap[currentLine + 1]; if (pos !== comment.pos) { // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); } // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); @@ -7365,7 +6149,7 @@ var ts; // More right indented comment */ --4 = 8 - 4 + 11 // class c { } // } - var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart); + var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); @@ -7383,45 +6167,45 @@ var ts; } } // Write the comment line text - writeTrimmedCurrentLine(pos, nextLineStart); + writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { // Single line comment of style //.... - writer.write(currentSourceFile.text.substring(comment.pos, comment.end)); - } - function writeTrimmedCurrentLine(pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); - var currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, ""); - if (currentLineText) { - // trimmed forward and ending spaces text - writer.write(currentLineText); - if (end !== comment.end) { - writer.writeLine(); - } - } - else { - // Empty string - make sure we write empty line - writer.writeLiteral(newLine); - } - } - function calculateIndent(pos, end) { - var currentLineIndent = 0; - for (; pos < end && ts.isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) { - if (currentSourceFile.text.charCodeAt(pos) === 9 /* tab */) { - // Tabs = TabSize = indent size and go to next tabStop - currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); - } - else { - // Single space - currentLineIndent++; - } - } - return currentLineIndent; + writer.write(text.substring(comment.pos, comment.end)); } } ts.writeCommentRange = writeCommentRange; + function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { + var end = Math.min(comment.end, nextLineStart - 1); + var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); + if (currentLineText) { + // trimmed forward and ending spaces text + writer.write(currentLineText); + if (end !== comment.end) { + writer.writeLine(); + } + } + else { + // Empty string - make sure we write empty line + writer.writeLiteral(newLine); + } + } + function calculateIndent(text, pos, end) { + var currentLineIndent = 0; + for (; pos < end && ts.isWhiteSpace(text.charCodeAt(pos)); pos++) { + if (text.charCodeAt(pos) === 9 /* tab */) { + // Tabs = TabSize = indent size and go to next tabStop + currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); + } + else { + // Single space + currentLineIndent++; + } + } + return currentLineIndent; + } function modifierToFlag(token) { switch (token) { case 113 /* StaticKeyword */: return 64 /* Static */; @@ -7517,14 +6301,14 @@ var ts; return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function isJavaScript(fileName) { - return ts.fileExtensionIs(fileName, ".js"); + function hasJavaScriptFileExtension(fileName) { + return ts.fileExtensionIs(fileName, ".js") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isJavaScript = isJavaScript; - function isTsx(fileName) { - return ts.fileExtensionIs(fileName, ".tsx"); + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function allowsJsxExpressions(fileName) { + return ts.fileExtensionIs(fileName, ".tsx") || ts.fileExtensionIs(fileName, ".jsx"); } - ts.isTsx = isTsx; + ts.allowsJsxExpressions = allowsJsxExpressions; /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences * representing the UTF-8 encoding of the character, and return the expanded char code list. @@ -7835,18 +6619,20 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; })(ts || (ts = {})); -/// /// +/// var ts; (function (ts) { - var nodeConstructors = new Array(272 /* Count */); /* @internal */ ts.parseTime = 0; - function getNodeConstructor(kind) { - return nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)); - } - ts.getNodeConstructor = getNodeConstructor; + var NodeConstructor; + var SourceFileConstructor; function createNode(kind, pos, end) { - return new (getNodeConstructor(kind))(pos, end); + if (kind === 248 /* SourceFile */) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + } + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + } } ts.createNode = createNode; function visitNode(cbNode, node) { @@ -8269,6 +7055,9 @@ var ts; // up by avoiding the cost of creating/compiling scanners over and over again. var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); var disallowInAndDecoratorContext = 1 /* DisallowIn */ | 4 /* Decorator */; + // capture constructors in 'initializeState' to avoid null checks + var NodeConstructor; + var SourceFileConstructor; var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -8354,13 +7143,16 @@ var ts; // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes) { - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor); + var isJavaScriptFile = ts.hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0; + initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor); var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes); clearState(); return result; } Parser.parseSourceFile = parseSourceFile; - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor) { + function initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); sourceText = _sourceText; syntaxCursor = _syntaxCursor; parseDiagnostics = []; @@ -8368,13 +7160,13 @@ var ts; identifiers = {}; identifierCount = 0; nodeCount = 0; - contextFlags = ts.isJavaScript(fileName) ? 32 /* JavaScriptFile */ : 0 /* None */; + contextFlags = isJavaScriptFile ? 32 /* JavaScriptFile */ : 0 /* None */; parseErrorBeforeNextFinishedNode = false; // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(ts.isTsx(fileName) ? 1 /* JSX */ : 0 /* Standard */); + scanner.setLanguageVariant(ts.allowsJsxExpressions(fileName) ? 1 /* JSX */ : 0 /* Standard */); } function clearState() { // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. @@ -8389,6 +7181,9 @@ var ts; } function parseSourceFileWorker(fileName, languageVersion, setParentNodes) { sourceFile = createSourceFile(fileName, languageVersion); + if (contextFlags & 32 /* JavaScriptFile */) { + sourceFile.parserContextFlags = 32 /* JavaScriptFile */; + } // Prime the scanner. token = nextToken(); processReferenceComments(sourceFile); @@ -8406,7 +7201,7 @@ var ts; // If this is a javascript file, proactively see if we can get JSDoc comments for // relevant nodes in the file. We'll use these to provide typing informaion if they're // available. - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { addJSDocComments(); } return sourceFile; @@ -8461,15 +7256,16 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion) { - var sourceFile = createNode(248 /* SourceFile */, /*pos*/ 0); - sourceFile.pos = 0; - sourceFile.end = sourceText.length; + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(248 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); + nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.languageVersion = languageVersion; sourceFile.fileName = ts.normalizePath(fileName); sourceFile.flags = ts.fileExtensionIs(sourceFile.fileName, ".d.ts") ? 4096 /* DeclarationFile */ : 0; - sourceFile.languageVariant = ts.isTsx(sourceFile.fileName) ? 1 /* JSX */ : 0 /* Standard */; + sourceFile.languageVariant = ts.allowsJsxExpressions(sourceFile.fileName) ? 1 /* JSX */ : 0 /* Standard */; return sourceFile; } function setContextFlag(val, flag) { @@ -8734,12 +7530,13 @@ var ts; return parseExpected(23 /* SemicolonToken */); } } + // note: this function creates only node function createNode(kind, pos) { nodeCount++; if (!(pos >= 0)) { pos = scanner.getStartPos(); } - return new (nodeConstructors[kind] || (nodeConstructors[kind] = ts.objectAllocator.getNodeConstructor(kind)))(pos, pos); + return new NodeConstructor(kind, pos, pos); } function finishNode(node, end) { node.end = end === undefined ? scanner.getStartPos() : end; @@ -8904,7 +7701,7 @@ var ts; case 12 /* ObjectLiteralMembers */: return token === 19 /* OpenBracketToken */ || token === 37 /* AsteriskToken */ || isLiteralPropertyName(); case 9 /* ObjectBindingElements */: - return isLiteralPropertyName(); + return token === 19 /* OpenBracketToken */ || isLiteralPropertyName(); case 7 /* HeritageClauseElement */: // If we see { } then only consume it as an expression if it is followed by , or { // That way we won't consume the body of a class in its heritage clause. @@ -9584,9 +8381,7 @@ var ts; } function parseParameterType() { if (parseOptional(54 /* ColonToken */)) { - return token === 9 /* StringLiteral */ - ? parseLiteralNode(/*internName*/ true) - : parseType(); + return parseType(); } return undefined; } @@ -9917,6 +8712,8 @@ var ts; // If these are followed by a dot, then parse these out as a dotted type reference instead. var node = tryParse(parseKeywordAndNoDot); return node || parseTypeReferenceOrTypePredicate(); + case 9 /* StringLiteral */: + return parseLiteralNode(/*internName*/ true); case 103 /* VoidKeyword */: case 97 /* ThisKeyword */: return parseTokenNode(); @@ -9946,6 +8743,7 @@ var ts; case 19 /* OpenBracketToken */: case 25 /* LessThanToken */: case 92 /* NewKeyword */: + case 9 /* StringLiteral */: return true; case 17 /* OpenParenToken */: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, @@ -10362,7 +9160,7 @@ var ts; return 1 /* True */; } // This *could* be a parenthesized arrow function. - // Return Unknown to let the caller know. + // Return Unknown to const the caller know. return 2 /* Unknown */; } else { @@ -10448,7 +9246,7 @@ var ts; // user meant to supply a block. For example, if the user wrote: // // a => - // let v = 0; + // const v = 0; // } // // they may be missing an open brace. Check to see if that's the case so we can @@ -10664,7 +9462,6 @@ var ts; var unaryOperator = token; var simpleUnaryExpression = parseSimpleUnaryExpression(); if (token === 38 /* AsteriskAsteriskToken */) { - var diagnostic; var start = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); if (simpleUnaryExpression.kind === 171 /* TypeAssertionExpression */) { parseErrorAtPosition(start, simpleUnaryExpression.end - start, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); @@ -11868,7 +10665,6 @@ var ts; } function parseObjectBindingElement() { var node = createNode(163 /* BindingElement */); - // TODO(andersh): Handle computed properties var tokenIsIdentifier = isIdentifier(); var propertyName = parsePropertyName(); if (tokenIsIdentifier && token !== 54 /* ColonToken */) { @@ -12691,7 +11487,7 @@ var ts; } JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); var jsDocTypeExpression = parseJSDocTypeExpression(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -12786,6 +11582,7 @@ var ts; case 103 /* VoidKeyword */: return parseTokenNode(); } + // TODO (drosen): Parse string literal types in JSDoc as well. return parseJSDocTypeReference(); } function parseJSDocThisType() { @@ -12957,7 +11754,7 @@ var ts; } } function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined); + initializeState("file.js", content, 2 /* Latest */, /*isJavaScriptFile*/ true, /*_syntaxCursor:*/ undefined); var jsDocComment = parseJSDocComment(/*parent:*/ undefined, start, length); var diagnostics = parseDiagnostics; clearState(); @@ -13682,6 +12479,1372 @@ var ts; })(InvalidPosition || (InvalidPosition = {})); })(IncrementalParser || (IncrementalParser = {})); })(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + ts.bindTime = 0; + (function (ModuleInstanceState) { + ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; + ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; + ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; + })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); + var ModuleInstanceState = ts.ModuleInstanceState; + var Reachability; + (function (Reachability) { + Reachability[Reachability["Unintialized"] = 1] = "Unintialized"; + Reachability[Reachability["Reachable"] = 2] = "Reachable"; + Reachability[Reachability["Unreachable"] = 4] = "Unreachable"; + Reachability[Reachability["ReportedUnreachable"] = 8] = "ReportedUnreachable"; + })(Reachability || (Reachability = {})); + function or(state1, state2) { + return (state1 | state2) & 2 /* Reachable */ + ? 2 /* Reachable */ + : (state1 & state2) & 8 /* ReportedUnreachable */ + ? 8 /* ReportedUnreachable */ + : 4 /* Unreachable */; + } + function getModuleInstanceState(node) { + // A module is uninstantiated if it contains only + // 1. interface declarations, type alias declarations + if (node.kind === 215 /* InterfaceDeclaration */ || node.kind === 216 /* TypeAliasDeclaration */) { + return 0 /* NonInstantiated */; + } + else if (ts.isConstEnumDeclaration(node)) { + return 2 /* ConstEnumOnly */; + } + else if ((node.kind === 222 /* ImportDeclaration */ || node.kind === 221 /* ImportEqualsDeclaration */) && !(node.flags & 2 /* Export */)) { + return 0 /* NonInstantiated */; + } + else if (node.kind === 219 /* ModuleBlock */) { + var state = 0 /* NonInstantiated */; + ts.forEachChild(node, function (n) { + switch (getModuleInstanceState(n)) { + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching + return false; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state = 2 /* ConstEnumOnly */; + return false; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state = 1 /* Instantiated */; + return true; + } + }); + return state; + } + else if (node.kind === 218 /* ModuleDeclaration */) { + return getModuleInstanceState(node.body); + } + else { + return 1 /* Instantiated */; + } + } + ts.getModuleInstanceState = getModuleInstanceState; + var ContainerFlags; + (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. + ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... + ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... + ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + ContainerFlags[ContainerFlags["HasLocals"] = 4] = "HasLocals"; + // If the current node is a container that also container that also contains locals. Examples: + // + // Functions, Methods, Modules, Source-files. + ContainerFlags[ContainerFlags["IsContainerWithLocals"] = 5] = "IsContainerWithLocals"; + })(ContainerFlags || (ContainerFlags = {})); + var binder = createBinder(); + function bindSourceFile(file, options) { + var start = new Date().getTime(); + binder(file, options); + ts.bindTime += new Date().getTime() - start; + } + ts.bindSourceFile = bindSourceFile; + function createBinder() { + var file; + var options; + var parent; + var container; + var blockScopeContainer; + var lastContainer; + var seenThisKeyword; + // state used by reachability checks + var hasExplicitReturn; + var currentReachabilityState; + var labelStack; + var labelIndexMap; + var implicitLabels; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). + var inStrictMode; + var symbolCount = 0; + var Symbol; + var classifiableNames; + function bindSourceFile(f, opts) { + file = f; + options = opts; + inStrictMode = !!file.externalModuleIndicator; + classifiableNames = {}; + Symbol = ts.objectAllocator.getSymbolConstructor(); + if (!file.locals) { + bind(file); + file.symbolCount = symbolCount; + file.classifiableNames = classifiableNames; + } + parent = undefined; + container = undefined; + blockScopeContainer = undefined; + lastContainer = undefined; + seenThisKeyword = false; + hasExplicitReturn = false; + labelStack = undefined; + labelIndexMap = undefined; + implicitLabels = undefined; + } + return bindSourceFile; + function createSymbol(flags, name) { + symbolCount++; + return new Symbol(flags, name); + } + function addDeclarationToSymbol(symbol, node, symbolFlags) { + symbol.flags |= symbolFlags; + node.symbol = symbol; + if (!symbol.declarations) { + symbol.declarations = []; + } + symbol.declarations.push(node); + if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { + symbol.exports = {}; + } + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { + symbol.members = {}; + } + if (symbolFlags & 107455 /* Value */ && !symbol.valueDeclaration) { + symbol.valueDeclaration = node; + } + } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. + function getDeclarationName(node) { + if (node.name) { + if (node.kind === 218 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */) { + return "\"" + node.name.text + "\""; + } + if (node.name.kind === 136 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; + } + ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); + return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + } + return node.name.text; + } + switch (node.kind) { + case 144 /* Constructor */: + return "__constructor"; + case 152 /* FunctionType */: + case 147 /* CallSignature */: + return "__call"; + case 153 /* ConstructorType */: + case 148 /* ConstructSignature */: + return "__new"; + case 149 /* IndexSignature */: + return "__index"; + case 228 /* ExportDeclaration */: + return "__export"; + case 227 /* ExportAssignment */: + return node.isExportEquals ? "export=" : "default"; + case 181 /* BinaryExpression */: + // Binary expression case is for JS module 'module.exports = expr' + return "export="; + case 213 /* FunctionDeclaration */: + case 214 /* ClassDeclaration */: + return node.flags & 512 /* Default */ ? "default" : undefined; + } + } + function getDisplayName(node) { + return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ + function declareSymbol(symbolTable, parent, node, includes, excludes) { + ts.Debug.assert(!ts.hasDynamicName(node)); + var isDefaultExport = node.flags & 512 /* Default */; + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var symbol; + if (name !== undefined) { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. + symbol = ts.hasProperty(symbolTable, name) + ? symbolTable[name] + : (symbolTable[name] = createSymbol(0 /* None */, name)); + if (name && (includes & 788448 /* Classifiable */)) { + classifiableNames[name] = name; + } + if (symbol.flags & excludes) { + if (node.name) { + node.name.parent = node; + } + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message = symbol.flags & 2 /* BlockScopedVariable */ + ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : ts.Diagnostics.Duplicate_identifier_0; + ts.forEach(symbol.declarations, function (declaration) { + if (declaration.flags & 512 /* Default */) { + message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; + } + }); + ts.forEach(symbol.declarations, function (declaration) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration))); + }); + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message, getDisplayName(node))); + symbol = createSymbol(0 /* None */, name); + } + } + else { + symbol = createSymbol(0 /* None */, "__missing"); + } + addDeclarationToSymbol(symbol, node, includes); + symbol.parent = parent; + return symbol; + } + function declareModuleMember(node, symbolFlags, symbolExcludes) { + var hasExportModifier = ts.getCombinedNodeFlags(node) & 2 /* Export */; + if (symbolFlags & 8388608 /* Alias */) { + if (node.kind === 230 /* ExportSpecifier */ || (node.kind === 221 /* ImportEqualsDeclaration */ && hasExportModifier)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, + // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set + // on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + if (hasExportModifier || container.flags & 131072 /* ExportContext */) { + var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | + (symbolFlags & 793056 /* Type */ ? 2097152 /* ExportType */ : 0) | + (symbolFlags & 1536 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); + var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + node.localSymbol = local; + return local; + } + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. + function bindChildren(node) { + // Before we recurse into a node's chilren, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. + var saveParent = parent; + var saveContainer = container; + var savedBlockScopeContainer = blockScopeContainer; + // This node will now be set as the parent of all of its children as we recurse into them. + parent = node; + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we proactively initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). + // + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. + // + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidently move any stale data forward from + // a previous compilation. + var containerFlags = getContainerFlags(node); + if (containerFlags & 1 /* IsContainer */) { + container = blockScopeContainer = node; + if (containerFlags & 4 /* HasLocals */) { + container.locals = {}; + } + addToContainerChain(container); + } + else if (containerFlags & 2 /* IsBlockScopedContainer */) { + blockScopeContainer = node; + blockScopeContainer.locals = undefined; + } + var savedReachabilityState; + var savedLabelStack; + var savedLabels; + var savedImplicitLabels; + var savedHasExplicitReturn; + var kind = node.kind; + var flags = node.flags; + // reset all reachability check related flags on node (for incremental scenarios) + flags &= ~1572864 /* ReachabilityCheckFlags */; + if (kind === 215 /* InterfaceDeclaration */) { + seenThisKeyword = false; + } + var saveState = kind === 248 /* SourceFile */ || kind === 219 /* ModuleBlock */ || ts.isFunctionLikeKind(kind); + if (saveState) { + savedReachabilityState = currentReachabilityState; + savedLabelStack = labelStack; + savedLabels = labelIndexMap; + savedImplicitLabels = implicitLabels; + savedHasExplicitReturn = hasExplicitReturn; + currentReachabilityState = 2 /* Reachable */; + hasExplicitReturn = false; + labelStack = labelIndexMap = implicitLabels = undefined; + } + bindReachableStatement(node); + if (currentReachabilityState === 2 /* Reachable */ && ts.isFunctionLikeKind(kind) && ts.nodeIsPresent(node.body)) { + flags |= 524288 /* HasImplicitReturn */; + if (hasExplicitReturn) { + flags |= 1048576 /* HasExplicitReturn */; + } + } + if (kind === 215 /* InterfaceDeclaration */) { + flags = seenThisKeyword ? flags | 262144 /* ContainsThis */ : flags & ~262144 /* ContainsThis */; + } + node.flags = flags; + if (saveState) { + hasExplicitReturn = savedHasExplicitReturn; + currentReachabilityState = savedReachabilityState; + labelStack = savedLabelStack; + labelIndexMap = savedLabels; + implicitLabels = savedImplicitLabels; + } + container = saveContainer; + parent = saveParent; + blockScopeContainer = savedBlockScopeContainer; + } + /** + * Returns true if node and its subnodes were successfully traversed. + * Returning false means that node was not examined and caller needs to dive into the node himself. + */ + function bindReachableStatement(node) { + if (checkUnreachable(node)) { + ts.forEachChild(node, bind); + return; + } + switch (node.kind) { + case 198 /* WhileStatement */: + bindWhileStatement(node); + break; + case 197 /* DoStatement */: + bindDoStatement(node); + break; + case 199 /* ForStatement */: + bindForStatement(node); + break; + case 200 /* ForInStatement */: + case 201 /* ForOfStatement */: + bindForInOrForOfStatement(node); + break; + case 196 /* IfStatement */: + bindIfStatement(node); + break; + case 204 /* ReturnStatement */: + case 208 /* ThrowStatement */: + bindReturnOrThrow(node); + break; + case 203 /* BreakStatement */: + case 202 /* ContinueStatement */: + bindBreakOrContinueStatement(node); + break; + case 209 /* TryStatement */: + bindTryStatement(node); + break; + case 206 /* SwitchStatement */: + bindSwitchStatement(node); + break; + case 220 /* CaseBlock */: + bindCaseBlock(node); + break; + case 207 /* LabeledStatement */: + bindLabeledStatement(node); + break; + default: + ts.forEachChild(node, bind); + break; + } + } + function bindWhileStatement(n) { + var preWhileState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + var postWhileState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + // bind expressions (don't affect reachability) + bind(n.expression); + currentReachabilityState = preWhileState; + var postWhileLabel = pushImplicitLabel(); + bind(n.statement); + popImplicitLabel(postWhileLabel, postWhileState); + } + function bindDoStatement(n) { + var preDoState = currentReachabilityState; + var postDoLabel = pushImplicitLabel(); + bind(n.statement); + var postDoState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : preDoState; + popImplicitLabel(postDoLabel, postDoState); + // bind expressions (don't affect reachability) + bind(n.expression); + } + function bindForStatement(n) { + var preForState = currentReachabilityState; + var postForLabel = pushImplicitLabel(); + // bind expressions (don't affect reachability) + bind(n.initializer); + bind(n.condition); + bind(n.incrementor); + bind(n.statement); + // for statement is considered infinite when it condition is either omitted or is true keyword + // - for(..;;..) + // - for(..;true;..) + var isInfiniteLoop = (!n.condition || n.condition.kind === 99 /* TrueKeyword */); + var postForState = isInfiniteLoop ? 4 /* Unreachable */ : preForState; + popImplicitLabel(postForLabel, postForState); + } + function bindForInOrForOfStatement(n) { + var preStatementState = currentReachabilityState; + var postStatementLabel = pushImplicitLabel(); + // bind expressions (don't affect reachability) + bind(n.initializer); + bind(n.expression); + bind(n.statement); + popImplicitLabel(postStatementLabel, preStatementState); + } + function bindIfStatement(n) { + // denotes reachability state when entering 'thenStatement' part of the if statement: + // i.e. if condition is false then thenStatement is unreachable + var ifTrueState = n.expression.kind === 84 /* FalseKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + // denotes reachability state when entering 'elseStatement': + // i.e. if condition is true then elseStatement is unreachable + var ifFalseState = n.expression.kind === 99 /* TrueKeyword */ ? 4 /* Unreachable */ : currentReachabilityState; + currentReachabilityState = ifTrueState; + // bind expression (don't affect reachability) + bind(n.expression); + bind(n.thenStatement); + if (n.elseStatement) { + var preElseState = currentReachabilityState; + currentReachabilityState = ifFalseState; + bind(n.elseStatement); + currentReachabilityState = or(currentReachabilityState, preElseState); + } + else { + currentReachabilityState = or(currentReachabilityState, ifFalseState); + } + } + function bindReturnOrThrow(n) { + // bind expression (don't affect reachability) + bind(n.expression); + if (n.kind === 204 /* ReturnStatement */) { + hasExplicitReturn = true; + } + currentReachabilityState = 4 /* Unreachable */; + } + function bindBreakOrContinueStatement(n) { + // call bind on label (don't affect reachability) + bind(n.label); + // for continue case touch label so it will be marked a used + var isValidJump = jumpToLabel(n.label, n.kind === 203 /* BreakStatement */ ? currentReachabilityState : 4 /* Unreachable */); + if (isValidJump) { + currentReachabilityState = 4 /* Unreachable */; + } + } + function bindTryStatement(n) { + // catch\finally blocks has the same reachability as try block + var preTryState = currentReachabilityState; + bind(n.tryBlock); + var postTryState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.catchClause); + var postCatchState = currentReachabilityState; + currentReachabilityState = preTryState; + bind(n.finallyBlock); + // post catch/finally state is reachable if + // - post try state is reachable - control flow can fall out of try block + // - post catch state is reachable - control flow can fall out of catch block + currentReachabilityState = or(postTryState, postCatchState); + } + function bindSwitchStatement(n) { + var preSwitchState = currentReachabilityState; + var postSwitchLabel = pushImplicitLabel(); + // bind expression (don't affect reachability) + bind(n.expression); + bind(n.caseBlock); + var hasDefault = ts.forEach(n.caseBlock.clauses, function (c) { return c.kind === 242 /* DefaultClause */; }); + // post switch state is unreachable if switch is exaustive (has a default case ) and does not have fallthrough from the last case + var postSwitchState = hasDefault && currentReachabilityState !== 2 /* Reachable */ ? 4 /* Unreachable */ : preSwitchState; + popImplicitLabel(postSwitchLabel, postSwitchState); + } + function bindCaseBlock(n) { + var startState = currentReachabilityState; + for (var _i = 0, _a = n.clauses; _i < _a.length; _i++) { + var clause = _a[_i]; + currentReachabilityState = startState; + bind(clause); + if (clause.statements.length && currentReachabilityState === 2 /* Reachable */ && options.noFallthroughCasesInSwitch) { + errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); + } + } + } + function bindLabeledStatement(n) { + // call bind on label (don't affect reachability) + bind(n.label); + var ok = pushNamedLabel(n.label); + bind(n.statement); + if (ok) { + popNamedLabel(n.label, currentReachabilityState); + } + } + function getContainerFlags(node) { + switch (node.kind) { + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + case 215 /* InterfaceDeclaration */: + case 217 /* EnumDeclaration */: + case 155 /* TypeLiteral */: + case 165 /* ObjectLiteralExpression */: + return 1 /* IsContainer */; + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + case 213 /* FunctionDeclaration */: + case 144 /* Constructor */: + case 145 /* GetAccessor */: + case 146 /* SetAccessor */: + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + case 218 /* ModuleDeclaration */: + case 248 /* SourceFile */: + case 216 /* TypeAliasDeclaration */: + return 5 /* IsContainerWithLocals */; + case 244 /* CatchClause */: + case 199 /* ForStatement */: + case 200 /* ForInStatement */: + case 201 /* ForOfStatement */: + case 220 /* CaseBlock */: + return 2 /* IsBlockScopedContainer */; + case 192 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Othewise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; + } + return 0 /* None */; + } + function addToContainerChain(next) { + if (lastContainer) { + lastContainer.nextContainer = next; + } + lastContainer = next; + } + function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { + // Just call this directly so that the return type of this function stays "void". + declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); + } + function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { + switch (container.kind) { + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 218 /* ModuleDeclaration */: + return declareModuleMember(node, symbolFlags, symbolExcludes); + case 248 /* SourceFile */: + return declareSourceFileMember(node, symbolFlags, symbolExcludes); + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + return declareClassMember(node, symbolFlags, symbolExcludes); + case 217 /* EnumDeclaration */: + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + case 155 /* TypeLiteral */: + case 165 /* ObjectLiteralExpression */: + case 215 /* InterfaceDeclaration */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). + return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + case 144 /* Constructor */: + case 145 /* GetAccessor */: + case 146 /* SetAccessor */: + case 213 /* FunctionDeclaration */: + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + case 216 /* TypeAliasDeclaration */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree. To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function declareClassMember(node, symbolFlags, symbolExcludes) { + return node.flags & 64 /* Static */ + ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + } + function declareSourceFileMember(node, symbolFlags, symbolExcludes) { + return ts.isExternalModule(file) + ? declareModuleMember(node, symbolFlags, symbolExcludes) + : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + } + function hasExportDeclarations(node) { + var body = node.kind === 248 /* SourceFile */ ? node : node.body; + if (body.kind === 248 /* SourceFile */ || body.kind === 219 /* ModuleBlock */) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var stat = _a[_i]; + if (stat.kind === 228 /* ExportDeclaration */ || stat.kind === 227 /* ExportAssignment */) { + return true; + } + } + } + return false; + } + function setExportContextFlag(node) { + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { + node.flags |= 131072 /* ExportContext */; + } + else { + node.flags &= ~131072 /* ExportContext */; + } + } + function bindModuleDeclaration(node) { + setExportContextFlag(node); + if (node.name.kind === 9 /* StringLiteral */) { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + } + else { + var state = getModuleInstanceState(node); + if (state === 0 /* NonInstantiated */) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { + // if module was already merged with some function, class or non-const enum + // treat is a non-const-enum-only + node.symbol.constEnumOnlyModule = false; + } + else { + var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; + if (node.symbol.constEnumOnlyModule === undefined) { + // non-merged case - use the current state + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; + } + else { + // merged case: module is const enum only if all its pieces are non-instantiated or const enum + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; + } + } + } + } + } + function bindFunctionOrConstructorType(node) { + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); + typeLiteralSymbol.members = (_a = {}, _a[symbol.name] = symbol, _a); + var _a; + } + function bindObjectLiteralExpression(node) { + var ElementKind; + (function (ElementKind) { + ElementKind[ElementKind["Property"] = 1] = "Property"; + ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; + })(ElementKind || (ElementKind = {})); + if (inStrictMode) { + var seen = {}; + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (prop.name.kind !== 69 /* Identifier */) { + continue; + } + var identifier = prop.name; + // ECMA-262 11.1.5 Object Initialiser + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 245 /* PropertyAssignment */ || prop.kind === 246 /* ShorthandPropertyAssignment */ || prop.kind === 143 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; + var existingKind = seen[identifier.text]; + if (!existingKind) { + seen[identifier.text] = currentKind; + continue; + } + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { + var span = ts.getErrorSpanForNode(file, identifier); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); + } + } + } + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); + } + function bindAnonymousDeclaration(node, symbolFlags, name) { + var symbol = createSymbol(symbolFlags, name); + addDeclarationToSymbol(symbol, node, symbolFlags); + } + function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { + switch (blockScopeContainer.kind) { + case 218 /* ModuleDeclaration */: + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + case 248 /* SourceFile */: + if (ts.isExternalModule(container)) { + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + } + // fall through. + default: + if (!blockScopeContainer.locals) { + blockScopeContainer.locals = {}; + addToContainerChain(blockScopeContainer); + } + declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + } + } + function bindBlockScopedVariableDeclaration(node) { + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); + } + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. + function checkStrictModeIdentifier(node) { + if (inStrictMode && + node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && + !ts.isIdentifierName(node)) { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + } + } + } + function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node) { + if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) + checkStrictModeEvalOrArguments(node, node.left); + } + } + function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments + if (inStrictMode && node.variableDeclaration) { + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); + } + } + function checkStrictModeDeleteExpression(node) { + // Grammar checking + if (inStrictMode && node.expression.kind === 69 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name + var span = ts.getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); + } + } + function isEvalOrArgumentsIdentifier(node) { + return node.kind === 69 /* Identifier */ && + (node.text === "eval" || node.text === "arguments"); + } + function checkStrictModeEvalOrArguments(contextNode, name) { + if (name && name.kind === 69 /* Identifier */) { + var identifier = name; + if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var span = ts.getErrorSpanForNode(file, name); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + } + } + } + function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + } + function checkStrictModeFunctionName(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) + checkStrictModeEvalOrArguments(node, node.name); + } + } + function checkStrictModeNumericLiteral(node) { + if (inStrictMode && node.flags & 32768 /* OctalLiteral */) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); + } + } + function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking + if (inStrictMode) { + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } + } + function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement + if (inStrictMode) { + errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + } + } + function errorOnFirstToken(node, message, arg0, arg1, arg2) { + var span = ts.getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + } + function getDestructuringParameterName(node) { + return "__" + ts.indexOf(node.parent.parameters, node); + } + function bind(node) { + if (!node) { + return; + } + node.parent = parent; + var savedInStrictMode = inStrictMode; + if (!savedInStrictMode) { + updateStrictMode(node); + } + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // However, not all symbols will end up in any of these tables. 'Anonymous' symbols + // (like TypeLiterals for example) will not be put in any table. + bindWorker(node); + // Then we recurse into the children of the node to bind them as well. For certain + // symbols we do specialized work when we recurse. For example, we'll keep track of + // the current 'container' node when it changes. This helps us know which symbol table + // a local should go into for example. + bindChildren(node); + inStrictMode = savedInStrictMode; + } + function updateStrictMode(node) { + switch (node.kind) { + case 248 /* SourceFile */: + case 219 /* ModuleBlock */: + updateStrictModeStatementList(node.statements); + return; + case 192 /* Block */: + if (ts.isFunctionLike(node.parent)) { + updateStrictModeStatementList(node.statements); + } + return; + case 214 /* ClassDeclaration */: + case 186 /* ClassExpression */: + // All classes are automatically in strict mode in ES6. + inStrictMode = true; + return; + } + } + function updateStrictModeStatementList(statements) { + for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { + var statement = statements_1[_i]; + if (!ts.isPrologueDirective(statement)) { + return; + } + if (isUseStrictPrologueDirective(statement)) { + inStrictMode = true; + return; + } + } + } + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) + function isUseStrictPrologueDirective(node) { + var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). + return nodeText === "\"use strict\"" || nodeText === "'use strict'"; + } + function bindWorker(node) { + switch (node.kind) { + /* Strict mode checks */ + case 69 /* Identifier */: + return checkStrictModeIdentifier(node); + case 181 /* BinaryExpression */: + if (ts.isInJavaScriptFile(node)) { + if (ts.isExportsPropertyAssignment(node)) { + bindExportsPropertyAssignment(node); + } + else if (ts.isModuleExportsAssignment(node)) { + bindModuleExportsAssignment(node); + } + } + return checkStrictModeBinaryExpression(node); + case 244 /* CatchClause */: + return checkStrictModeCatchClause(node); + case 175 /* DeleteExpression */: + return checkStrictModeDeleteExpression(node); + case 8 /* NumericLiteral */: + return checkStrictModeNumericLiteral(node); + case 180 /* PostfixUnaryExpression */: + return checkStrictModePostfixUnaryExpression(node); + case 179 /* PrefixUnaryExpression */: + return checkStrictModePrefixUnaryExpression(node); + case 205 /* WithStatement */: + return checkStrictModeWithStatement(node); + case 97 /* ThisKeyword */: + seenThisKeyword = true; + return; + case 137 /* TypeParameter */: + return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530912 /* TypeParameterExcludes */); + case 138 /* Parameter */: + return bindParameter(node); + case 211 /* VariableDeclaration */: + case 163 /* BindingElement */: + return bindVariableDeclarationOrBindingElement(node); + case 141 /* PropertyDeclaration */: + case 140 /* PropertySignature */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 107455 /* PropertyExcludes */); + case 245 /* PropertyAssignment */: + case 246 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 107455 /* PropertyExcludes */); + case 247 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 107455 /* EnumMemberExcludes */); + case 147 /* CallSignature */: + case 148 /* ConstructSignature */: + case 149 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 143 /* MethodDeclaration */: + case 142 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 107455 /* PropertyExcludes */ : 99263 /* MethodExcludes */); + case 213 /* FunctionDeclaration */: + checkStrictModeFunctionName(node); + return declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); + case 144 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 145 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); + case 146 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); + case 152 /* FunctionType */: + case 153 /* ConstructorType */: + return bindFunctionOrConstructorType(node); + case 155 /* TypeLiteral */: + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); + case 165 /* ObjectLiteralExpression */: + return bindObjectLiteralExpression(node); + case 173 /* FunctionExpression */: + case 174 /* ArrowFunction */: + checkStrictModeFunctionName(node); + var bindingName = node.name ? node.name.text : "__function"; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); + case 168 /* CallExpression */: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; + // Members of classes, interfaces, and modules + case 186 /* ClassExpression */: + case 214 /* ClassDeclaration */: + return bindClassLikeDeclaration(node); + case 215 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 792960 /* InterfaceExcludes */); + case 216 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793056 /* TypeAliasExcludes */); + case 217 /* EnumDeclaration */: + return bindEnumDeclaration(node); + case 218 /* ModuleDeclaration */: + return bindModuleDeclaration(node); + // Imports and exports + case 221 /* ImportEqualsDeclaration */: + case 224 /* NamespaceImport */: + case 226 /* ImportSpecifier */: + case 230 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + case 223 /* ImportClause */: + return bindImportClause(node); + case 228 /* ExportDeclaration */: + return bindExportDeclaration(node); + case 227 /* ExportAssignment */: + return bindExportAssignment(node); + case 248 /* SourceFile */: + return bindSourceFileIfExternalModule(); + } + } + function bindSourceFileIfExternalModule() { + setExportContextFlag(file); + if (ts.isExternalModule(file)) { + bindSourceFileAsExternalModule(); + } + } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } + function bindExportAssignment(node) { + var boundExpression = node.kind === 227 /* ExportAssignment */ ? node.expression : node.right; + if (!container.symbol || !container.symbol.exports) { + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); + } + else if (boundExpression.kind === 69 /* Identifier */) { + // An export default clause with an identifier exports all meanings of that identifier + declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* Alias */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + else { + // An export default clause with an expression exports a value + declareSymbol(container.symbol.exports, container.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + } + function bindExportDeclaration(node) { + if (!container.symbol || !container.symbol.exports) { + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); + } + else if (!node.exportClause) { + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); + } + } + function bindImportClause(node) { + if (node.name) { + declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + } + } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); + } + } + function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); + } + function bindModuleExportsAssignment(node) { + // 'module.exports = expr' assignment + setCommonJsModuleIndicator(node); + bindExportAssignment(node); + } + function bindCallExpression(node) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node)) { + setCommonJsModuleIndicator(node); + } + } + function bindClassLikeDeclaration(node) { + if (node.kind === 214 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); + } + else { + var bindingName = node.name ? node.name.text : "__class"; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier + if (node.name) { + classifiableNames[node.name.text] = node.name.text; + } + } + var symbol = node.symbol; + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); + if (ts.hasProperty(symbol.exports, prototypeSymbol.name)) { + if (node.name) { + node.name.parent = node; + } + file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); + } + symbol.exports[prototypeSymbol.name] = prototypeSymbol; + prototypeSymbol.parent = symbol; + } + function bindEnumDeclaration(node) { + return ts.isConst(node) + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + } + function bindVariableDeclarationOrBindingElement(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (!ts.isBindingPattern(node.name)) { + if (ts.isBlockOrCatchScoped(node)) { + bindBlockScopedVariableDeclaration(node); + } + else if (ts.isParameterDeclaration(node)) { + // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); + } + } + } + function bindParameter(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) + checkStrictModeEvalOrArguments(node, node.name); + } + if (ts.isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); + } + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + } + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + if (node.flags & 56 /* AccessibilityModifier */ && + node.parent.kind === 144 /* Constructor */ && + ts.isClassLike(node.parent.parent)) { + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */, 107455 /* PropertyExcludes */); + } + } + function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { + return ts.hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); + } + // reachability checks + function pushNamedLabel(name) { + initializeReachabilityStateIfNecessary(); + if (ts.hasProperty(labelIndexMap, name.text)) { + return false; + } + labelIndexMap[name.text] = labelStack.push(1 /* Unintialized */) - 1; + return true; + } + function pushImplicitLabel() { + initializeReachabilityStateIfNecessary(); + var index = labelStack.push(1 /* Unintialized */) - 1; + implicitLabels.push(index); + return index; + } + function popNamedLabel(label, outerState) { + var index = labelIndexMap[label.text]; + ts.Debug.assert(index !== undefined); + ts.Debug.assert(labelStack.length == index + 1); + labelIndexMap[label.text] = undefined; + setCurrentStateAtLabel(labelStack.pop(), outerState, label); + } + function popImplicitLabel(implicitLabelIndex, outerState) { + if (labelStack.length !== implicitLabelIndex + 1) { + ts.Debug.assert(false, "Label stack: " + labelStack.length + ", index:" + implicitLabelIndex); + } + var i = implicitLabels.pop(); + if (implicitLabelIndex !== i) { + ts.Debug.assert(false, "i: " + i + ", index: " + implicitLabelIndex); + } + setCurrentStateAtLabel(labelStack.pop(), outerState, /*name*/ undefined); + } + function setCurrentStateAtLabel(innerMergedState, outerState, label) { + if (innerMergedState === 1 /* Unintialized */) { + if (label && !options.allowUnusedLabels) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(label, ts.Diagnostics.Unused_label)); + } + currentReachabilityState = outerState; + } + else { + currentReachabilityState = or(innerMergedState, outerState); + } + } + function jumpToLabel(label, outerState) { + initializeReachabilityStateIfNecessary(); + var index = label ? labelIndexMap[label.text] : ts.lastOrUndefined(implicitLabels); + if (index === undefined) { + // reference to unknown label or + // break/continue used outside of loops + return false; + } + var stateAtLabel = labelStack[index]; + labelStack[index] = stateAtLabel === 1 /* Unintialized */ ? outerState : or(stateAtLabel, outerState); + return true; + } + function checkUnreachable(node) { + switch (currentReachabilityState) { + case 4 /* Unreachable */: + var reportError = + // report error on all statements except empty ones + (ts.isStatement(node) && node.kind !== 194 /* EmptyStatement */) || + // report error on class declarations + node.kind === 214 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 218 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 217 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + if (reportError) { + currentReachabilityState = 8 /* ReportedUnreachable */; + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ + var reportUnreachableCode = !options.allowUnreachableCode && + !ts.isInAmbientContext(node) && + (node.kind !== 193 /* VariableStatement */ || + ts.getCombinedNodeFlags(node.declarationList) & 24576 /* BlockScoped */ || + ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); + if (reportUnreachableCode) { + errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + } + } + case 8 /* ReportedUnreachable */: + return true; + default: + return false; + } + function shouldReportErrorOnModuleDeclaration(node) { + var instanceState = getModuleInstanceState(node); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + } + } + function initializeReachabilityStateIfNecessary() { + if (labelIndexMap) { + return; + } + currentReachabilityState = 2 /* Reachable */; + labelIndexMap = {}; + labelStack = []; + implicitLabels = []; + } + } +})(ts || (ts = {})); /// /* @internal */ var ts; @@ -13755,7 +13918,7 @@ var ts; symbolToString: symbolToString, getAugmentedPropertiesOfType: getAugmentedPropertiesOfType, getRootSymbols: getRootSymbols, - getContextualType: getContextualType, + getContextualType: getApparentTypeOfContextualType, getFullyQualifiedName: getFullyQualifiedName, getResolvedSignature: getResolvedSignature, getConstantValue: getConstantValue, @@ -14025,7 +14188,7 @@ var ts; return ts.getAncestor(node, 248 /* SourceFile */); } function isGlobalSourceFile(node) { - return node.kind === 248 /* SourceFile */ && !ts.isExternalModule(node); + return node.kind === 248 /* SourceFile */ && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning && ts.hasProperty(symbols, name)) { @@ -14127,15 +14290,24 @@ var ts; } switch (location.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location)) + if (!ts.isExternalOrCommonJsModule(location)) break; case 218 /* ModuleDeclaration */: var moduleExports = getSymbolOfNode(location).exports; if (location.kind === 248 /* SourceFile */ || (location.kind === 218 /* ModuleDeclaration */ && location.name.kind === 9 /* StringLiteral */)) { - // It's an external module. Because of module/namespace merging, a module's exports are in scope, - // yet we never want to treat an export specifier as putting a member in scope. Therefore, - // if the name we find is purely an export specifier, it is not actually considered in scope. + // It's an external module. First see if the module has an export default and if the local + // name of that export default matches. + if (result = moduleExports["default"]) { + var localSymbol = ts.getLocalSymbolForExportDefault(result); + if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { + break loop; + } + result = undefined; + } + // Because of module/namespace merging, a module's exports are in scope, + // yet we never want to treat an export specifier as putting a member in scope. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope. // Two things to note about this: // 1. We have to check this without calling getSymbol. The problem with calling getSymbol // on an export specifier is that it might find the export specifier itself, and try to @@ -14149,12 +14321,6 @@ var ts; ts.getDeclarationOfKind(moduleExports[name], 230 /* ExportSpecifier */)) { break; } - result = moduleExports["default"]; - var localSymbol = ts.getLocalSymbolForExportDefault(result); - if (result && localSymbol && (result.flags & meaning) && localSymbol.name === name) { - break loop; - } - result = undefined; } if (result = getSymbol(moduleExports, name, meaning & 8914931 /* ModuleMember */)) { break loop; @@ -14297,7 +14463,7 @@ var ts; // declare module foo { // interface bar {} // } - // let foo/*1*/: foo/*2*/.bar; + // const foo/*1*/: foo/*2*/.bar; // The foo at /*1*/ and /*2*/ will share same symbol with two meaning // block - scope variable and namespace module. However, only when we // try to resolve name in /*1*/ which is used in variable position, @@ -14601,6 +14767,9 @@ var ts; if (moduleName === undefined) { return; } + if (moduleName.indexOf("!") >= 0) { + moduleName = moduleName.substr(0, moduleName.indexOf("!")); + } var isRelative = ts.isExternalModuleNameRelative(moduleName); if (!isRelative) { var symbol = getSymbol(globals, "\"" + moduleName + "\"", 512 /* ValueModule */); @@ -14788,7 +14957,7 @@ var ts; } switch (location_1.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location_1)) { + if (!ts.isExternalOrCommonJsModule(location_1)) { break; } case 218 /* ModuleDeclaration */: @@ -14910,7 +15079,7 @@ var ts; // export class c { // } // } - // let x: typeof m.c + // const x: typeof m.c // In the above example when we start with checking if typeof m.c symbol is accessible, // we are going to see if c can be accessed in scope directly. // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible @@ -14949,7 +15118,7 @@ var ts; } function hasExternalModuleSymbol(declaration) { return (declaration.kind === 218 /* ModuleDeclaration */ && declaration.name.kind === 9 /* StringLiteral */) || - (declaration.kind === 248 /* SourceFile */ && ts.isExternalModule(declaration)); + (declaration.kind === 248 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol) { var aliasesToMakeVisible; @@ -15100,7 +15269,7 @@ var ts; parentSymbol = symbol; appendSymbolNameOnly(symbol, writer); } - // Let the writer know we just wrote out a symbol. The declaration emitter writer uses + // const the writer know we just wrote out a symbol. The declaration emitter writer uses // this to determine if an import it has previously seen (and not written out) needs // to be written to the file once the walk of the tree is complete. // @@ -15181,7 +15350,7 @@ var ts; writeAnonymousType(type, flags); } else if (type.flags & 256 /* StringLiteral */) { - writer.writeStringLiteral(type.text); + writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); } else { // Should never get here @@ -15568,7 +15737,7 @@ var ts; } } else if (node.kind === 248 /* SourceFile */) { - return ts.isExternalModule(node) ? node : undefined; + return ts.isExternalOrCommonJsModule(node) ? node : undefined; } } ts.Debug.fail("getContainingModule cant reach here"); @@ -15650,7 +15819,7 @@ var ts; // Private/protected properties/methods are not visible return false; } - // Public properties/methods are visible if its parents are visible, so let it fall into next case statement + // Public properties/methods are visible if its parents are visible, so const it fall into next case statement case 144 /* Constructor */: case 148 /* ConstructSignature */: case 147 /* CallSignature */: @@ -15678,7 +15847,7 @@ var ts; // Source file is always visible case 248 /* SourceFile */: return true; - // Export assignements do not create name bindings outside the module + // Export assignments do not create name bindings outside the module case 227 /* ExportAssignment */: return false; default: @@ -15814,6 +15983,23 @@ var ts; var symbol = getSymbolOfNode(node); return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node); } + function getTextOfPropertyName(name) { + switch (name.kind) { + case 69 /* Identifier */: + return name.text; + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + return name.text; + case 136 /* ComputedPropertyName */: + if (ts.isStringOrNumericLiteral(name.expression.kind)) { + return name.expression.text; + } + } + return undefined; + } + function isComputedNonLiteralName(name) { + return name.kind === 136 /* ComputedPropertyName */ && !ts.isStringOrNumericLiteral(name.expression.kind); + } // Return the inferred type for a binding element function getTypeForBindingElement(declaration) { var pattern = declaration.parent; @@ -15835,10 +16021,15 @@ var ts; if (pattern.kind === 161 /* ObjectBindingPattern */) { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) var name_10 = declaration.propertyName || declaration.name; + if (isComputedNonLiteralName(name_10)) { + // computed properties with non-literal names are treated as 'any' + return anyType; + } // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. - type = getTypeOfPropertyOfType(parentType, name_10.text) || - isNumericLiteralName(name_10.text) && getIndexTypeOfType(parentType, 1 /* Number */) || + var text = getTextOfPropertyName(name_10); + type = getTypeOfPropertyOfType(parentType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!type) { error(name_10, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_10)); @@ -15938,10 +16129,17 @@ var ts; // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern, includePatternInType) { var members = {}; + var hasComputedProperties = false; ts.forEach(pattern.elements, function (e) { - var flags = 4 /* Property */ | 67108864 /* Transient */ | (e.initializer ? 536870912 /* Optional */ : 0); var name = e.propertyName || e.name; - var symbol = createSymbol(flags, name.text); + if (isComputedNonLiteralName(name)) { + // do not include computed properties in the implied type + hasComputedProperties = true; + return; + } + var text = getTextOfPropertyName(name); + var flags = 4 /* Property */ | 67108864 /* Transient */ | (e.initializer ? 536870912 /* Optional */ : 0); + var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType); symbol.bindingElement = e; members[symbol.name] = symbol; @@ -15950,6 +16148,9 @@ var ts; if (includePatternInType) { result.pattern = pattern; } + if (hasComputedProperties) { + result.flags |= 67108864 /* ObjectLiteralPatternWithComputedProperties */; + } return result; } // Return the type implied by an array binding pattern @@ -16026,6 +16227,14 @@ var ts; if (declaration.kind === 227 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } + // Handle module.exports = expr + if (declaration.kind === 181 /* BinaryExpression */) { + return links.type = checkExpression(declaration.right); + } + // Handle exports.p = expr + if (declaration.kind === 166 /* PropertyAccessExpression */) { + return checkExpressionCached(declaration.parent.right); + } // Handle variable, parameter or property if (!pushTypeResolution(symbol, 0 /* Type */)) { return unknownType; @@ -16304,23 +16513,25 @@ var ts; } function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; - var baseContructorType = getBaseConstructorTypeOfClass(type); - if (!(baseContructorType.flags & 80896 /* ObjectType */)) { + var baseConstructorType = getBaseConstructorTypeOfClass(type); + if (!(baseConstructorType.flags & 80896 /* ObjectType */)) { return; } var baseTypeNode = getBaseTypeNodeOfClass(type); var baseType; - if (baseContructorType.symbol && baseContructorType.symbol.flags & 32 /* Class */) { - // When base constructor type is a class we know that the constructors all have the same type parameters as the + var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 /* Class */ && + areAllOuterTypeParametersApplied(originalBaseType)) { + // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the // class and all return the instance type of the class. There is no need for further checks and we can apply the // type arguments in the same manner as a type reference to get the same error reporting experience. - baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol); + baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } else { // The class derives from a "class-like" constructor function, check that we have at least one construct signature // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere // we check that all instantiated signatures return the same type. - var constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments); + var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); return; @@ -16345,6 +16556,17 @@ var ts; type.resolvedBaseTypes.push(baseType); } } + function areAllOuterTypeParametersApplied(type) { + // An unapplied type parameter has its symbol still the same as the matching argument symbol. + // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. + var outerTypeParameters = type.outerTypeParameters; + if (outerTypeParameters) { + var last = outerTypeParameters.length - 1; + var typeArguments = type.typeArguments; + return outerTypeParameters[last].symbol !== typeArguments[last].symbol; + } + return true; + } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { @@ -16424,7 +16646,7 @@ var ts; type.typeArguments = type.typeParameters; type.thisType = createType(512 /* TypeParameter */ | 33554432 /* ThisType */); type.thisType.symbol = symbol; - type.thisType.constraint = getTypeWithThisArgument(type); + type.thisType.constraint = type; } } return links.declaredType; @@ -16939,6 +17161,20 @@ var ts; type = getApparentType(type); return type.flags & 49152 /* UnionOrIntersection */ ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } + /** + * The apparent type of a type parameter is the base constraint instantiated with the type parameter + * as the type argument for the 'this' type. + */ + function getApparentTypeOfTypeParameter(type) { + if (!type.resolvedApparentType) { + var constraintType = getConstraintOfTypeParameter(type); + while (constraintType && constraintType.flags & 512 /* TypeParameter */) { + constraintType = getConstraintOfTypeParameter(constraintType); + } + type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type); + } + return type.resolvedApparentType; + } /** * For a type parameter, return the base constraint of the type parameter. For the string, number, * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the @@ -16946,12 +17182,7 @@ var ts; */ function getApparentType(type) { if (type.flags & 512 /* TypeParameter */) { - do { - type = getConstraintOfTypeParameter(type); - } while (type && type.flags & 512 /* TypeParameter */); - if (!type) { - type = emptyObjectType; - } + type = getApparentTypeOfTypeParameter(type); } if (type.flags & 258 /* StringLike */) { type = globalStringType; @@ -17116,7 +17347,7 @@ var ts; if (node.initializer) { var signatureDeclaration = node.parent; var signature = getSignatureFromDeclaration(signatureDeclaration); - var parameterIndex = signatureDeclaration.parameters.indexOf(node); + var parameterIndex = ts.indexOf(signatureDeclaration.parameters, node); ts.Debug.assert(parameterIndex >= 0); return parameterIndex >= signature.minArgumentCount; } @@ -17217,6 +17448,16 @@ var ts; } return result; } + function resolveExternalModuleTypeByLiteral(name) { + var moduleSym = resolveExternalModuleName(name, name); + if (moduleSym) { + var resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + return getTypeOfSymbol(resolvedModuleSymbol); + } + } + return anyType; + } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { if (!pushTypeResolution(signature, 3 /* ResolvedReturnType */)) { @@ -17740,11 +17981,12 @@ var ts; return links.resolvedType; } function getStringLiteralType(node) { - if (ts.hasProperty(stringLiteralTypes, node.text)) { - return stringLiteralTypes[node.text]; + var text = node.text; + if (ts.hasProperty(stringLiteralTypes, text)) { + return stringLiteralTypes[text]; } - var type = stringLiteralTypes[node.text] = createType(256 /* StringLiteral */); - type.text = ts.getTextOfNode(node); + var type = stringLiteralTypes[text] = createType(256 /* StringLiteral */); + type.text = text; return type; } function getTypeFromStringLiteral(node) { @@ -18265,7 +18507,7 @@ var ts; return false; } function hasExcessProperties(source, target, reportErrors) { - if (someConstituentTypeHasKind(target, 80896 /* ObjectType */)) { + if (!(target.flags & 67108864 /* ObjectLiteralPatternWithComputedProperties */) && someConstituentTypeHasKind(target, 80896 /* ObjectType */)) { for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (!isKnownProperty(target, prop.name)) { @@ -18358,9 +18600,6 @@ var ts; return result; } function typeParameterIdenticalTo(source, target) { - if (source.symbol.name !== target.symbol.name) { - return 0 /* False */; - } // covers case when both type parameters does not have constraint (both equal to noConstraintType) if (source.constraint === target.constraint) { return -1 /* True */; @@ -18852,18 +19091,29 @@ var ts; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } + function isMatchingSignature(source, target, partialMatch) { + // A source signature matches a target signature if the two signatures have the same number of required, + // optional, and rest parameters. + if (source.parameters.length === target.parameters.length && + source.minArgumentCount === target.minArgumentCount && + source.hasRestParameter === target.hasRestParameter) { + return true; + } + // A source signature partially matches a target signature if the target signature has no fewer required + // parameters and no more overall parameters than the source signature (where a signature with a rest + // parameter is always considered to have more overall parameters than one without). + if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (source.hasRestParameter && !target.hasRestParameter || + source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) { + return true; + } + return false; + } function compareSignatures(source, target, partialMatch, ignoreReturnTypes, compareTypes) { if (source === target) { return -1 /* True */; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { - if (!partialMatch || - source.parameters.length < target.parameters.length && !source.hasRestParameter || - source.minArgumentCount > target.minArgumentCount) { - return 0 /* False */; - } + if (!(isMatchingSignature(source, target, partialMatch))) { + return 0 /* False */; } var result = -1 /* True */; if (source.typeParameters && target.typeParameters) { @@ -18957,6 +19207,9 @@ var ts; function isTupleLikeType(type) { return !!getPropertyOfType(type, "0"); } + function isStringLiteralType(type) { + return type.flags & 256 /* StringLiteral */; + } /** * Check if a Type was written as a tuple type literal. * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. @@ -19629,7 +19882,7 @@ var ts; } function narrowTypeByInstanceof(type, expr, assumeTrue) { // Check that type is not any, assumed result is true, and we have variable symbol on the left - if (isTypeAny(type) || !assumeTrue || expr.left.kind !== 69 /* Identifier */ || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || expr.left.kind !== 69 /* Identifier */ || getResolvedSymbol(expr.left) !== symbol) { return type; } // Check that right operand is a function type with a prototype property @@ -19660,6 +19913,12 @@ var ts; } } if (targetType) { + if (!assumeTrue) { + if (type.flags & 16384 /* Union */) { + return getUnionType(ts.filter(type.types, function (t) { return !isTypeSubtypeOf(t, targetType); })); + } + return type; + } return getNarrowedType(type, targetType); } return type; @@ -20129,6 +20388,9 @@ var ts; function getIndexTypeOfContextualType(type, kind) { return applyToContextualType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }); } + function contextualTypeIsStringLiteralType(type) { + return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, isStringLiteralType) : isStringLiteralType(type)); + } // Return true if the given contextual type is a tuple-like type function contextualTypeIsTupleLikeType(type) { return !!(type.flags & 16384 /* Union */ ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); @@ -20150,7 +20412,7 @@ var ts; } function getContextualTypeForObjectLiteralElement(element) { var objectLiteral = element.parent; - var type = getContextualType(objectLiteral); + var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!ts.hasDynamicName(element)) { // For a (non-symbol) computed property, there is no reason to look up the name @@ -20173,7 +20435,7 @@ var ts; // type of T. function getContextualTypeForElementExpression(node) { var arrayLiteral = node.parent; - var type = getContextualType(arrayLiteral); + var type = getApparentTypeOfContextualType(arrayLiteral); if (type) { var index = ts.indexOf(arrayLiteral.elements, node); return getTypeOfPropertyOfContextualType(type, "" + index) @@ -20206,11 +20468,28 @@ var ts; } // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. - function getContextualType(node) { - var type = getContextualTypeWorker(node); + function getApparentTypeOfContextualType(node) { + var type = getContextualType(node); return type && getApparentType(type); } - function getContextualTypeWorker(node) { + /** + * Woah! Do you really want to use this function? + * + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, + * you probably meant to use 'getApparentTypeOfContextualType'. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContetxualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. + * + * @param node the expression whose contextual type will be returned. + * @returns the contextual type of an expression. + */ + function getContextualType(node) { if (isInsideWithStatementBody(node)) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; @@ -20285,7 +20564,7 @@ var ts; ts.Debug.assert(node.kind !== 143 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var type = ts.isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node) - : getContextualType(node); + : getApparentTypeOfContextualType(node); if (!type) { return undefined; } @@ -20411,7 +20690,7 @@ var ts; type.pattern = node; return type; } - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting @@ -20494,10 +20773,11 @@ var ts; checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable = {}; var propertiesArray = []; - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === 161 /* ObjectBindingPattern */ || contextualType.pattern.kind === 165 /* ObjectLiteralExpression */); var typeFlags = 0; + var patternWithComputedProperties = false; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var memberDecl = _a[_i]; var member = memberDecl.symbol; @@ -20525,8 +20805,11 @@ var ts; if (isOptional) { prop.flags |= 536870912 /* Optional */; } + if (ts.hasDynamicName(memberDecl)) { + patternWithComputedProperties = true; + } } - else if (contextualTypeHasPattern) { + else if (contextualTypeHasPattern && !(contextualType.flags & 67108864 /* ObjectLiteralPatternWithComputedProperties */)) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. var impliedProp = getPropertyOfType(contextualType, member.name); @@ -20578,7 +20861,7 @@ var ts; var numberIndexType = getIndexType(1 /* Number */); var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType); var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 1048576 /* FreshObjectLiteral */; - result.flags |= 524288 /* ObjectLiteral */ | 4194304 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 14680064 /* PropagatingFlags */); + result.flags |= 524288 /* ObjectLiteral */ | 4194304 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 14680064 /* PropagatingFlags */) | (patternWithComputedProperties ? 67108864 /* ObjectLiteralPatternWithComputedProperties */ : 0); if (inDestructuringPattern) { result.pattern = node; } @@ -21289,7 +21572,7 @@ var ts; // so order how inherited signatures are processed is still preserved. // interface A { (x: string): void } // interface B extends A { (x: 'foo'): string } - // let b: B; + // const b: B; // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function reorderCandidates(signatures, result) { var lastParent; @@ -22247,6 +22530,10 @@ var ts; return anyType; } } + // In JavaScript files, calls to any identifier 'require' are treated as external module imports + if (ts.isInJavaScriptFile(node) && ts.isRequireCall(node)) { + return resolveExternalModuleTypeByLiteral(node.arguments[0]); + } return getReturnTypeOfSignature(signature); } function checkTaggedTemplateExpression(node) { @@ -22257,7 +22544,10 @@ var ts; var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { var widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { + // Permit 'number[] | "foo"' to be asserted to 'string'. + var bothAreStringLike = someConstituentTypeHasKind(targetType, 258 /* StringLike */) && + someConstituentTypeHasKind(widenedType, 258 /* StringLike */); + if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { checkTypeAssignableTo(exprType, targetType, node, ts.Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } @@ -22801,19 +23091,26 @@ var ts; for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { var p = properties_3[_i]; if (p.kind === 245 /* PropertyAssignment */ || p.kind === 246 /* ShorthandPropertyAssignment */) { - // TODO(andersh): Computed property support var name_13 = p.name; + if (name_13.kind === 136 /* ComputedPropertyName */) { + checkComputedPropertyName(name_13); + } + if (isComputedNonLiteralName(name_13)) { + continue; + } + var text = getTextOfPropertyName(name_13); var type = isTypeAny(sourceType) ? sourceType - : getTypeOfPropertyOfType(sourceType, name_13.text) || - isNumericLiteralName(name_13.text) && getIndexTypeOfType(sourceType, 1 /* Number */) || + : getTypeOfPropertyOfType(sourceType, text) || + isNumericLiteralName(text) && getIndexTypeOfType(sourceType, 1 /* Number */) || getIndexTypeOfType(sourceType, 0 /* String */); if (type) { if (p.kind === 246 /* ShorthandPropertyAssignment */) { checkDestructuringAssignment(p, type); } else { - checkDestructuringAssignment(p.initializer || name_13, type); + // non-shorthand property assignments should always have initializers + checkDestructuringAssignment(p.initializer, type); } } else { @@ -23014,6 +23311,10 @@ var ts; case 31 /* ExclamationEqualsToken */: case 32 /* EqualsEqualsEqualsToken */: case 33 /* ExclamationEqualsEqualsToken */: + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (someConstituentTypeHasKind(leftType, 258 /* StringLike */) && someConstituentTypeHasKind(rightType, 258 /* StringLike */)) { + return booleanType; + } if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { reportOperatorError(); } @@ -23137,6 +23438,13 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getUnionType([type1, type2]); } + function checkStringLiteralExpression(node) { + var contextualType = getContextualType(node); + if (contextualType && contextualTypeIsStringLiteralType(contextualType)) { + return getStringLiteralType(node); + } + return stringType; + } function checkTemplateExpression(node) { // We just want to check each expressions, but we are unconcerned with // the type of each expression, as any value may be coerced into a string. @@ -23187,7 +23495,7 @@ var ts; if (isInferentialContext(contextualMapper)) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { - var contextualType = getContextualType(node); + var contextualType = getApparentTypeOfContextualType(node); if (contextualType) { var contextualSignature = getSingleCallSignature(contextualType); if (contextualSignature && !contextualSignature.typeParameters) { @@ -23251,6 +23559,7 @@ var ts; case 183 /* TemplateExpression */: return checkTemplateExpression(node); case 9 /* StringLiteral */: + return checkStringLiteralExpression(node); case 11 /* NoSubstitutionTemplateLiteral */: return stringType; case 10 /* RegularExpressionLiteral */: @@ -24580,7 +24889,7 @@ var ts; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 248 /* SourceFile */ && ts.isExternalModule(parent)) { + if (parent.kind === 248 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent)) { // If the declaration happens to be in external module, report error that require and exports are reserved keywords error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } @@ -24598,15 +24907,15 @@ var ts; // A non-initialized declaration is a no-op as the block declaration will resolve before the var // declaration. the problem is if the declaration has an initializer. this will act as a write to the // block declared value. this is fine for let, but not const. - // Only consider declarations with initializers, uninitialized let declarations will not + // Only consider declarations with initializers, uninitialized const declarations will not // step on a let/const variable. - // Do not consider let and const declarations, as duplicate block-scoped declarations + // Do not consider const and const declarations, as duplicate block-scoped declarations // are handled by the binder. - // We are only looking for let declarations that step on let\const declarations from a + // We are only looking for const declarations that step on let\const declarations from a // different scope. e.g.: // { // const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration - // let x = 0; // symbol for this declaration will be 'symbol' + // const x = 0; // symbol for this declaration will be 'symbol' // } // skip block-scoped variables and parameters if ((ts.getCombinedNodeFlags(node) & 24576 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { @@ -24693,6 +25002,12 @@ var ts; checkExpressionCached(node.initializer); } } + if (node.kind === 163 /* BindingElement */) { + // check computed properties inside property names of binding elements + if (node.propertyName && node.propertyName.kind === 136 /* ComputedPropertyName */) { + checkComputedPropertyName(node.propertyName); + } + } // For a binding pattern, check contained binding elements if (ts.isBindingPattern(node.name)) { ts.forEach(node.name.elements, checkSourceElement); @@ -25176,6 +25491,7 @@ var ts; var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); + var expressionTypeIsStringLike = someConstituentTypeHasKind(expressionType, 258 /* StringLike */); ts.forEach(node.caseBlock.clauses, function (clause) { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause if (clause.kind === 242 /* DefaultClause */ && !hasDuplicateDefaultClause) { @@ -25195,6 +25511,10 @@ var ts; // TypeScript 1.0 spec (April 2014):5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. var caseType = checkExpression(caseClause.expression); + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, 258 /* StringLike */)) { + return; + } if (!isTypeAssignableTo(expressionType, caseType)) { // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); @@ -25659,11 +25979,14 @@ var ts; var enumIsConst = ts.isConst(node); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.name.kind === 136 /* ComputedPropertyName */) { + if (isComputedNonLiteralName(member.name)) { error(member.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums); } - else if (isNumericLiteralName(member.name.text)) { - error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + else { + var text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text)) { + error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + } } var previousEnumMemberIsNonConstant = autoValue === undefined; var initializer = member.initializer; @@ -26305,8 +26628,8 @@ var ts; } // Function and class expression bodies are checked after all statements in the enclosing body. This is // to ensure constructs like the following are permitted: - // let foo = function () { - // let s = foo(); + // const foo = function () { + // const s = foo(); // return "hello"; // } // Here, performing a full type check of the body of the function expression whilst in the process of @@ -26421,8 +26744,12 @@ var ts; if (!(links.flags & 1 /* TypeChecked */)) { // Check whether the file has declared it is the default lib, // and whether the user has specifically chosen to avoid checking it. - if (node.isDefaultLib && compilerOptions.skipDefaultLibCheck) { - return; + if (compilerOptions.skipDefaultLibCheck) { + // If the user specified '--noLib' and a file has a '/// ', + // then we should treat that file as a default lib. + if (node.hasNoDefaultLib) { + return; + } } // Grammar checking checkGrammarSourceFile(node); @@ -26432,7 +26759,7 @@ var ts; potentialThisCollisions.length = 0; ts.forEach(node.statements, checkSourceElement); checkFunctionAndClassExpressionBodies(node); - if (ts.isExternalModule(node)) { + if (ts.isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); } if (potentialThisCollisions.length) { @@ -26515,7 +26842,7 @@ var ts; } switch (location.kind) { case 248 /* SourceFile */: - if (!ts.isExternalModule(location)) { + if (!ts.isExternalOrCommonJsModule(location)) { break; } case 218 /* ModuleDeclaration */: @@ -27153,9 +27480,18 @@ var ts; getReferencedValueDeclaration: getReferencedValueDeclaration, getTypeReferenceSerializationKind: getTypeReferenceSerializationKind, isOptionalParameter: isOptionalParameter, - isArgumentsLocalBinding: isArgumentsLocalBinding + isArgumentsLocalBinding: isArgumentsLocalBinding, + getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration }; } + function getExternalModuleFileFromDeclaration(declaration) { + var specifier = ts.getExternalModuleName(declaration); + var moduleSymbol = getSymbolAtLocation(specifier); + if (!moduleSymbol) { + return undefined; + } + return ts.getDeclarationOfKind(moduleSymbol, 248 /* SourceFile */); + } function initializeTypeChecker() { // Bind all source files and propagate errors ts.forEach(host.getSourceFiles(), function (file) { @@ -27163,11 +27499,10 @@ var ts; }); // Initialize global symbol table ts.forEach(host.getSourceFiles(), function (file) { - if (!ts.isExternalModule(file)) { + if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } }); - // Initialize special symbols getSymbolLinks(undefinedSymbol).type = undefinedType; getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments"); getSymbolLinks(unknownSymbol).type = unknownType; @@ -27866,7 +28201,7 @@ var ts; } } function checkGrammarForNonSymbolComputedProperty(node, message) { - if (node.kind === 136 /* ComputedPropertyName */ && !ts.isWellKnownSymbolSyntactically(node.expression)) { + if (ts.isDynamicName(node)) { return grammarErrorOnNode(node, message); } } @@ -28225,11 +28560,15 @@ var ts; var writeTextOfNode; var writer = createAndSetNewTextWriterWithSymbolWriter(); var enclosingDeclaration; - var currentSourceFile; + var currentText; + var currentLineMap; + var currentIdentifiers; + var isCurrentFileExternalModule; var reportedDeclarationError = false; var errorNameNode; var emitJsDocComments = compilerOptions.removeComments ? function (declaration) { } : writeJsDocComments; var emit = compilerOptions.stripInternal ? stripInternal : emitNode; + var noDeclare = !root; var moduleElementDeclarationEmitInfo = []; var asynchronousSubModuleDeclarationEmitInfo; // Contains the reference paths that needs to go in the declaration file. @@ -28272,23 +28611,56 @@ var ts; else { // Emit references corresponding to this file var emittedReferencedFiles = []; + var prevModuleElementDeclarationEmitInfo = []; ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + if (!ts.isDeclarationFile(sourceFile)) { // Check what references need to be added if (!compilerOptions.noResolve) { ts.forEach(sourceFile.referencedFiles, function (fileReference) { var referencedFile = ts.tryResolveScriptReference(host, sourceFile, fileReference); - // If the reference file is a declaration file or an external module, emit that reference - if (referencedFile && (ts.isExternalModuleOrDeclarationFile(referencedFile) && + // If the reference file is a declaration file, emit that reference + if (referencedFile && (ts.isDeclarationFile(referencedFile) && !ts.contains(emittedReferencedFiles, referencedFile))) { writeReferencePath(referencedFile); emittedReferencedFiles.push(referencedFile); } }); } + } + if (!ts.isExternalModuleOrDeclarationFile(sourceFile)) { + noDeclare = false; emitSourceFile(sourceFile); } + else if (ts.isExternalModule(sourceFile)) { + noDeclare = true; + write("declare module \"" + ts.getResolvedExternalModuleName(host, sourceFile) + "\" {"); + writeLine(); + increaseIndent(); + emitSourceFile(sourceFile); + decreaseIndent(); + write("}"); + writeLine(); + // create asynchronous output for the importDeclarations + if (moduleElementDeclarationEmitInfo.length) { + var oldWriter = writer; + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.isVisible && !aliasEmitInfo.asynchronousOutput) { + ts.Debug.assert(aliasEmitInfo.node.kind === 222 /* ImportDeclaration */); + createAndSetNewTextWriterWithSymbolWriter(); + ts.Debug.assert(aliasEmitInfo.indent === 1); + increaseIndent(); + writeImportDeclaration(aliasEmitInfo.node); + aliasEmitInfo.asynchronousOutput = writer.getText(); + decreaseIndent(); + } + }); + setWriter(oldWriter); + } + prevModuleElementDeclarationEmitInfo = prevModuleElementDeclarationEmitInfo.concat(moduleElementDeclarationEmitInfo); + moduleElementDeclarationEmitInfo = []; + } }); + moduleElementDeclarationEmitInfo = moduleElementDeclarationEmitInfo.concat(prevModuleElementDeclarationEmitInfo); } return { reportedDeclarationError: reportedDeclarationError, @@ -28297,13 +28669,12 @@ var ts; referencePathsOutput: referencePathsOutput }; function hasInternalAnnotation(range) { - var text = currentSourceFile.text; - var comment = text.substring(range.pos, range.end); + var comment = currentText.substring(range.pos, range.end); return comment.indexOf("@internal") >= 0; } function stripInternal(node) { if (node) { - var leadingCommentRanges = ts.getLeadingCommentRanges(currentSourceFile.text, node.pos); + var leadingCommentRanges = ts.getLeadingCommentRanges(currentText, node.pos); if (ts.forEach(leadingCommentRanges, hasInternalAnnotation)) { return; } @@ -28395,7 +28766,7 @@ var ts; var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult); if (errorInfo) { if (errorInfo.typeName) { - diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); + diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); } else { diagnostics.push(ts.createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorModuleName)); @@ -28461,10 +28832,10 @@ var ts; } function writeJsDocComments(declaration) { if (declaration) { - var jsDocComments = ts.getJsDocComments(declaration, currentSourceFile); - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments); + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); } } function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { @@ -28481,7 +28852,7 @@ var ts; case 103 /* VoidKeyword */: case 97 /* ThisKeyword */: case 9 /* StringLiteral */: - return writeTextOfNode(currentSourceFile, type); + return writeTextOfNode(currentText, type); case 188 /* ExpressionWithTypeArguments */: return emitExpressionWithTypeArguments(type); case 151 /* TypeReference */: @@ -28512,14 +28883,14 @@ var ts; } function writeEntityName(entityName) { if (entityName.kind === 69 /* Identifier */) { - writeTextOfNode(currentSourceFile, entityName); + writeTextOfNode(currentText, entityName); } else { var left = entityName.kind === 135 /* QualifiedName */ ? entityName.left : entityName.expression; var right = entityName.kind === 135 /* QualifiedName */ ? entityName.right : entityName.name; writeEntityName(left); write("."); - writeTextOfNode(currentSourceFile, right); + writeTextOfNode(currentText, right); } } function emitEntityName(entityName) { @@ -28549,7 +28920,7 @@ var ts; } } function emitTypePredicate(type) { - writeTextOfNode(currentSourceFile, type.parameterName); + writeTextOfNode(currentText, type.parameterName); write(" is "); emitType(type.type); } @@ -28590,9 +28961,12 @@ var ts; } } function emitSourceFile(node) { - currentSourceFile = node; + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); enclosingDeclaration = node; - ts.emitDetachedComments(currentSourceFile, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); emitLines(node.statements); } // Return a temp variable name to be used in `export default` statements. @@ -28601,13 +28975,13 @@ var ts; // do not need to keep track of created temp names. function getExportDefaultTempVariableName() { var baseName = "_default"; - if (!ts.hasProperty(currentSourceFile.identifiers, baseName)) { + if (!ts.hasProperty(currentIdentifiers, baseName)) { return baseName; } var count = 0; while (true) { var name_18 = baseName + "_" + (++count); - if (!ts.hasProperty(currentSourceFile.identifiers, name_18)) { + if (!ts.hasProperty(currentIdentifiers, name_18)) { return name_18; } } @@ -28615,7 +28989,7 @@ var ts; function emitExportAssignment(node) { if (node.expression.kind === 69 /* Identifier */) { write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentSourceFile, node.expression); + writeTextOfNode(currentText, node.expression); } else { // Expression @@ -28653,7 +29027,7 @@ var ts; writeModuleElement(node); } else if (node.kind === 221 /* ImportEqualsDeclaration */ || - (node.parent.kind === 248 /* SourceFile */ && ts.isExternalModule(currentSourceFile))) { + (node.parent.kind === 248 /* SourceFile */ && isCurrentFileExternalModule)) { var isVisible; if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 248 /* SourceFile */) { // Import declaration of another module that is visited async so lets put it in right spot @@ -28707,7 +29081,7 @@ var ts; } function emitModuleElementDeclarationFlags(node) { // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent === currentSourceFile) { + if (node.parent.kind === 248 /* SourceFile */) { // If the node is exported if (node.flags & 2 /* Export */) { write("export "); @@ -28715,7 +29089,7 @@ var ts; if (node.flags & 512 /* Default */) { write("default "); } - else if (node.kind !== 215 /* InterfaceDeclaration */) { + else if (node.kind !== 215 /* InterfaceDeclaration */ && !noDeclare) { write("declare "); } } @@ -28742,7 +29116,7 @@ var ts; write("export "); } write("import "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" = "); if (ts.isInternalModuleImportEqualsDeclaration(node)) { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); @@ -28750,7 +29124,7 @@ var ts; } else { write("require("); - writeTextOfNode(currentSourceFile, ts.getExternalModuleImportEqualsDeclarationExpression(node)); + writeTextOfNode(currentText, ts.getExternalModuleImportEqualsDeclarationExpression(node)); write(");"); } writer.writeLine(); @@ -28785,7 +29159,7 @@ var ts; if (node.importClause) { var currentWriterPos = writer.getTextPos(); if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentSourceFile, node.importClause.name); + writeTextOfNode(currentText, node.importClause.name); } if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { if (currentWriterPos !== writer.getTextPos()) { @@ -28794,7 +29168,7 @@ var ts; } if (node.importClause.namedBindings.kind === 224 /* NamespaceImport */) { write("* as "); - writeTextOfNode(currentSourceFile, node.importClause.namedBindings.name); + writeTextOfNode(currentText, node.importClause.namedBindings.name); } else { write("{ "); @@ -28804,16 +29178,28 @@ var ts; } write(" from "); } - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); write(";"); writer.writeLine(); } + function emitExternalModuleSpecifier(moduleSpecifier) { + if (moduleSpecifier.kind === 9 /* StringLiteral */ && (!root) && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, moduleSpecifier.parent); + if (moduleName) { + write("\""); + write(moduleName); + write("\""); + return; + } + } + writeTextOfNode(currentText, moduleSpecifier); + } function emitImportOrExportSpecifier(node) { if (node.propertyName) { - writeTextOfNode(currentSourceFile, node.propertyName); + writeTextOfNode(currentText, node.propertyName); write(" as "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } function emitExportSpecifier(node) { emitImportOrExportSpecifier(node); @@ -28835,7 +29221,7 @@ var ts; } if (node.moduleSpecifier) { write(" from "); - writeTextOfNode(currentSourceFile, node.moduleSpecifier); + emitExternalModuleSpecifier(node.moduleSpecifier); } write(";"); writer.writeLine(); @@ -28849,11 +29235,11 @@ var ts; else { write("module "); } - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); while (node.body.kind !== 219 /* ModuleBlock */) { node = node.body; write("."); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; @@ -28872,7 +29258,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); @@ -28894,7 +29280,7 @@ var ts; write("const "); } write("enum "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); write(" {"); writeLine(); increaseIndent(); @@ -28905,7 +29291,7 @@ var ts; } function emitEnumMemberDeclaration(node) { emitJsDocComments(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var enumMemberValue = resolver.getConstantValue(node); if (enumMemberValue !== undefined) { write(" = "); @@ -28922,7 +29308,7 @@ var ts; increaseIndent(); emitJsDocComments(node); decreaseIndent(); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If there is constraint present and this is not a type parameter of the private method emit the constraint if (node.constraint && !isPrivateMethodTypeParameter(node)) { write(" extends "); @@ -29037,7 +29423,7 @@ var ts; write("abstract "); } write("class "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -29060,7 +29446,7 @@ var ts; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("interface "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); var prevEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = node; emitTypeParameters(node.typeParameters); @@ -29095,7 +29481,7 @@ var ts; // If this node is a computed name, it can only be a symbol, because we've already skipped // it if it's not a well known symbol. In that case, the text of the name will be exactly // what we want, namely the name expression enclosed in brackets. - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If optional property emit ? if ((node.kind === 141 /* PropertyDeclaration */ || node.kind === 140 /* PropertySignature */) && ts.hasQuestionToken(node)) { write("?"); @@ -29177,7 +29563,7 @@ var ts; emitBindingPattern(bindingElement.name); } else { - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); } } @@ -29221,7 +29607,7 @@ var ts; emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.setAccessor); emitClassMemberDeclarationFlags(node); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (!(node.flags & 16 /* Private */)) { accessorWithTypeAnnotation = node; var type = getTypeAnnotationFromAccessor(node); @@ -29307,13 +29693,13 @@ var ts; } if (node.kind === 213 /* FunctionDeclaration */) { write("function "); - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } else if (node.kind === 144 /* Constructor */) { write("constructor"); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); if (ts.hasQuestionToken(node)) { write("?"); } @@ -29437,7 +29823,7 @@ var ts; emitBindingPattern(node.name); } else { - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); } if (resolver.isOptionalParameter(node)) { write("?"); @@ -29552,7 +29938,7 @@ var ts; // Example: // original: function foo({y: [a,b,c]}) {} // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; - writeTextOfNode(currentSourceFile, bindingElement.propertyName); + writeTextOfNode(currentText, bindingElement.propertyName); write(": "); } if (bindingElement.name) { @@ -29575,7 +29961,7 @@ var ts; if (bindingElement.dotDotDotToken) { write("..."); } - writeTextOfNode(currentSourceFile, bindingElement.name); + writeTextOfNode(currentText, bindingElement.name); } } } @@ -29667,6 +30053,18 @@ var ts; return ts.isExternalModule(sourceFile) || ts.isDeclarationFile(sourceFile); } ts.isExternalModuleOrDeclarationFile = isExternalModuleOrDeclarationFile; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || ts.isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; var Jump; (function (Jump) { Jump[Jump["Break"] = 2] = "Break"; @@ -29954,15 +30352,19 @@ var ts; var newLine = host.getNewLine(); var jsxDesugaring = host.getCompilerOptions().jsx !== 1 /* Preserve */; var shouldEmitJsx = function (s) { return (s.languageVariant === 1 /* JSX */ && !jsxDesugaring); }; + var outFile = compilerOptions.outFile || compilerOptions.out; + var emitJavaScript = createFileEmitter(); if (targetSourceFile === undefined) { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { - var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); - emitFile(jsFilePath, sourceFile); - } - }); - if (compilerOptions.outFile || compilerOptions.out) { - emitFile(compilerOptions.outFile || compilerOptions.out); + if (outFile) { + emitFile(outFile); + } + else { + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if (ts.shouldEmitToOwnFile(sourceFile, compilerOptions)) { + var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js"); + emitFile(jsFilePath, sourceFile); + } + }); } } else { @@ -29971,8 +30373,8 @@ var ts; var jsFilePath = ts.getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js"); emitFile(jsFilePath, targetSourceFile); } - else if (!ts.isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) { - emitFile(compilerOptions.outFile || compilerOptions.out); + else if (!ts.isDeclarationFile(targetSourceFile) && outFile) { + emitFile(outFile); } } // Sort and make the unique list of diagnostics @@ -30024,10 +30426,16 @@ var ts; } } } - function emitJavaScript(jsFilePath, root) { + function createFileEmitter() { var writer = ts.createTextWriter(newLine); var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; var currentSourceFile; + var currentText; + var currentLineMap; + var currentFileIdentifiers; + var renamedDependencies; + var isEs6Module; + var isCurrentFileExternalModule; // name of an exporter function if file is a System external module // System.register([...], function () {...}) // exporting in System modules looks like: @@ -30035,15 +30443,15 @@ var ts; // => // var x;... exporter("x", x = 1) var exportFunctionForFile; - var generatedNameSet = {}; - var nodeToGeneratedName = []; + var generatedNameSet; + var nodeToGeneratedName; var computedPropertyNamesToGeneratedNames; var convertedLoopState; - var extendsEmitted = false; - var decorateEmitted = false; - var paramEmitted = false; - var awaiterEmitted = false; - var tempFlags = 0; + var extendsEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var tempFlags; var tempVariables; var tempParameters; var externalImports; @@ -30075,6 +30483,8 @@ var ts; var scopeEmitEnd = function () { }; /** Sourcemap data that will get encoded */ var sourceMapData; + /** The root file passed to the emit function (if present) */ + var root; /** If removeComments is true, no leading-comments needed to be emitted **/ var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; var moduleEmitDelegates = (_a = {}, @@ -30085,31 +30495,77 @@ var ts; _a[1 /* CommonJS */] = emitCommonJSModule, _a ); - if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { - initializeEmitterWithSourceMaps(); - } - if (root) { - // Do not call emit directly. It does not set the currentSourceFile. - emitSourceFile(root); - } - else { - ts.forEach(host.getSourceFiles(), function (sourceFile) { - if (!isExternalModuleOrDeclarationFile(sourceFile)) { - emitSourceFile(sourceFile); + var bundleEmitDelegates = (_b = {}, + _b[5 /* ES6 */] = function () { }, + _b[2 /* AMD */] = emitAMDModule, + _b[4 /* System */] = emitSystemModule, + _b[3 /* UMD */] = function () { }, + _b[1 /* CommonJS */] = function () { }, + _b + ); + return doEmit; + function doEmit(jsFilePath, rootFile) { + // reset the state + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = {}; + nodeToGeneratedName = []; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = rootFile; + if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { + initializeEmitterWithSourceMaps(jsFilePath, root); + } + if (root) { + // Do not call emit directly. It does not set the currentSourceFile. + emitSourceFile(root); + } + else { + if (modulekind) { + ts.forEach(host.getSourceFiles(), emitEmitHelpers); } - }); + ts.forEach(host.getSourceFiles(), function (sourceFile) { + if ((!isExternalModuleOrDeclarationFile(sourceFile)) || (modulekind && ts.isExternalModule(sourceFile))) { + emitSourceFile(sourceFile); + } + }); + } + writeLine(); + writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM); } - writeLine(); - writeEmittedFiles(writer.getText(), /*writeByteOrderMark*/ compilerOptions.emitBOM); - return; function emitSourceFile(sourceFile) { currentSourceFile = sourceFile; + currentText = sourceFile.text; + currentLineMap = ts.getLineStarts(sourceFile); exportFunctionForFile = undefined; + isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; + renamedDependencies = sourceFile.renamedDependencies; + currentFileIdentifiers = sourceFile.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(sourceFile); emit(sourceFile); } function isUniqueName(name) { return !resolver.hasGlobalName(name) && - !ts.hasProperty(currentSourceFile.identifiers, name) && + !ts.hasProperty(currentFileIdentifiers, name) && !ts.hasProperty(generatedNameSet, name); } // Return the next available name in the pattern _a ... _z, _0, _1, ... @@ -30192,7 +30648,7 @@ var ts; var id = ts.getNodeId(node); return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); } - function initializeEmitterWithSourceMaps() { + function initializeEmitterWithSourceMaps(jsFilePath, root) { var sourceMapDir; // The directory in which sourcemap will be // Current source map file and its index in the sources list var sourceMapSourceIndex = -1; @@ -30280,7 +30736,7 @@ var ts; } } function recordSourceMapSpan(pos) { - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + var sourceLinePos = ts.computeLineAndCharacterOfPosition(currentLineMap, pos); // Convert the location to be one-based. sourceLinePos.line++; sourceLinePos.character++; @@ -30314,13 +30770,13 @@ var ts; } function recordEmitNodeStartSpan(node) { // Get the token pos after skipping to the token (ignoring the leading trivia) - recordSourceMapSpan(ts.skipTrivia(currentSourceFile.text, node.pos)); + recordSourceMapSpan(ts.skipTrivia(currentText, node.pos)); } function recordEmitNodeEndSpan(node) { recordSourceMapSpan(node.end); } function writeTextWithSpanRecord(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos); + var tokenStartPos = ts.skipTrivia(currentText, startPos); recordSourceMapSpan(tokenStartPos); var tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn); recordSourceMapSpan(tokenEndPos); @@ -30402,9 +30858,9 @@ var ts; sourceMapNameIndices.pop(); } ; - function writeCommentRangeWithMap(curentSourceFile, writer, comment, newLine) { + function writeCommentRangeWithMap(currentText, currentLineMap, writer, comment, newLine) { recordSourceMapSpan(comment.pos); - ts.writeCommentRange(currentSourceFile, writer, comment, newLine); + ts.writeCommentRange(currentText, currentLineMap, writer, comment, newLine); recordSourceMapSpan(comment.end); } function serializeSourceMapContents(version, file, sourceRoot, sources, names, mappings, sourcesContent) { @@ -30434,7 +30890,7 @@ var ts; return output; } } - function writeJavaScriptAndSourceMapFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptAndSourceMapFile(emitOutput, jsFilePath, writeByteOrderMark) { encodeLastRecordedSourceMapSpan(); var sourceMapText = serializeSourceMapContents(3, sourceMapData.sourceMapFile, sourceMapData.sourceMapSourceRoot, sourceMapData.sourceMapSources, sourceMapData.sourceMapNames, sourceMapData.sourceMapMappings, sourceMapData.sourceMapSourcesContent); sourceMapDataList.push(sourceMapData); @@ -30450,7 +30906,7 @@ var ts; sourceMapUrl = "//# sourceMappingURL=" + sourceMapData.jsSourceMappingURL; } // Write sourcemap url to the js file and write the js file - writeJavaScriptFile(emitOutput + sourceMapUrl, writeByteOrderMark); + writeJavaScriptFile(emitOutput + sourceMapUrl, jsFilePath, writeByteOrderMark); } // Initialize source map data var sourceMapJsFile = ts.getBaseFileName(ts.normalizeSlashes(jsFilePath)); @@ -30522,7 +30978,7 @@ var ts; scopeEmitEnd = recordScopeNameEnd; writeComment = writeCommentRangeWithMap; } - function writeJavaScriptFile(emitOutput, writeByteOrderMark) { + function writeJavaScriptFile(emitOutput, jsFilePath, writeByteOrderMark) { ts.writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark); } // Create a temporary variable with a unique unused name. @@ -30702,7 +31158,7 @@ var ts; // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. if (node.parent) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + return ts.getTextOfNodeFromSourceText(currentText, node); } // If we can't reach the original source text, use the canonical form if it's a number, // or an escaped quoted form of the original text if it's string-like. @@ -30729,7 +31185,7 @@ var ts; // Find original source text, since we need to emit the raw strings of the tagged template. // The raw strings contain the (escaped) strings of what the user wrote. // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + var text = ts.getTextOfNodeFromSourceText(currentText, node); // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), // thus we need to remove those characters. // First template piece starts with "`", others with "}" @@ -31146,7 +31602,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } write("\""); } @@ -31246,7 +31702,7 @@ var ts; // Identifier references named import write(getGeneratedNameForNode(declaration.parent.parent.parent)); var name_23 = declaration.propertyName || declaration.name; - var identifier = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, name_23); + var identifier = ts.getTextOfNodeFromSourceText(currentText, name_23); if (languageVersion === 0 /* ES3 */ && identifier === "default") { write("[\"default\"]"); } @@ -31270,7 +31726,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function isNameOfNestedRedeclaration(node) { @@ -31308,7 +31764,7 @@ var ts; write(node.text); } else { - writeTextOfNode(currentSourceFile, node); + writeTextOfNode(currentText, node); } } function emitThis(node) { @@ -31712,7 +32168,7 @@ var ts; function emitShorthandPropertyAssignment(node) { // The name property of a short-hand property assignment is considered an expression position, so here // we manually emit the identifier to avoid rewriting. - writeTextOfNode(currentSourceFile, node.name); + writeTextOfNode(currentText, node.name); // If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier, // we emit a normal property assignment. For example: // module m { @@ -31722,7 +32178,7 @@ var ts; // let obj = { y }; // } // Here we need to emit obj = { y : m.y } regardless of the output target. - if (languageVersion < 2 /* ES6 */ || isNamespaceExportReference(node.name)) { + if (modulekind !== 5 /* ES6 */ || isNamespaceExportReference(node.name)) { // Emit identifier as an identifier write(": "); emit(node.name); @@ -31779,11 +32235,11 @@ var ts; var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); // 1 .toString is a valid property access, emit a space after the literal // Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal - var shouldEmitSpace; + var shouldEmitSpace = false; if (!indentedBeforeDot) { if (node.expression.kind === 8 /* NumericLiteral */) { // check if numeric literal was originally written with a dot - var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node.expression); + var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); shouldEmitSpace = text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; } else { @@ -32962,16 +33418,16 @@ var ts; emitToken(16 /* CloseBraceToken */, node.clauses.end); } function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node1.pos)) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, node2.end); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); } function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPosition(currentSourceFile, node1.end) === - ts.getLineOfLocalPosition(currentSourceFile, ts.skipTrivia(currentSourceFile.text, node2.pos)); + return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === + ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); } function emitCaseOrDefaultClause(node) { if (node.kind === 241 /* CaseClause */) { @@ -33077,7 +33533,7 @@ var ts; ts.Debug.assert(!!(node.flags & 512 /* Default */) || node.kind === 227 /* ExportAssignment */); // only allow export default at a source file level if (modulekind === 1 /* CommonJS */ || modulekind === 2 /* AMD */ || modulekind === 3 /* UMD */) { - if (!currentSourceFile.symbol.exports["___esModule"]) { + if (!isEs6Module) { if (languageVersion === 1 /* ES5 */) { // default value of configurable, enumerable, writable are `false`. write("Object.defineProperty(exports, \"__esModule\", { value: true });"); @@ -33272,14 +33728,20 @@ var ts; return node; } function createPropertyAccessForDestructuringProperty(object, propName) { - // We create a synthetic copy of the identifier in order to avoid the rewriting that might - // otherwise occur when the identifier is emitted. - var syntheticName = ts.createSynthesizedNode(propName.kind); - syntheticName.text = propName.text; - if (syntheticName.kind !== 69 /* Identifier */) { - return createElementAccessExpression(object, syntheticName); + var index; + var nameIsComputed = propName.kind === 136 /* ComputedPropertyName */; + if (nameIsComputed) { + index = ensureIdentifier(propName.expression, /* reuseIdentifierExpression */ false); } - return createPropertyAccessExpression(object, syntheticName); + else { + // We create a synthetic copy of the identifier in order to avoid the rewriting that might + // otherwise occur when the identifier is emitted. + index = ts.createSynthesizedNode(propName.kind); + index.text = propName.text; + } + return !nameIsComputed && index.kind === 69 /* Identifier */ + ? createPropertyAccessExpression(object, index) + : createElementAccessExpression(object, index); } function createSliceCall(value, sliceIndex) { var call = ts.createSynthesizedNode(168 /* CallExpression */); @@ -33742,7 +34204,6 @@ var ts; var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); var isArrowFunction = node.kind === 174 /* ArrowFunction */; var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 4096 /* CaptureArguments */) !== 0; - var args; // An async function is emit as an outer function that calls an inner // generator function. To preserve lexical bindings, we pass the current // `this` and `arguments` objects to `__awaiter`. The generator function @@ -35197,8 +35658,8 @@ var ts; * Here we check if alternative name was provided for a given moduleName and return it if possible. */ function tryRenameExternalModule(moduleName) { - if (currentSourceFile.renamedDependencies && ts.hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) { - return "\"" + currentSourceFile.renamedDependencies[moduleName.text] + "\""; + if (renamedDependencies && ts.hasProperty(renamedDependencies, moduleName.text)) { + return "\"" + renamedDependencies[moduleName.text] + "\""; } return undefined; } @@ -35351,7 +35812,7 @@ var ts; // - current file is not external module // - import declaration is top level and target is value imported by entity name if (resolver.isReferencedAliasDeclaration(node) || - (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { + (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { emitLeadingComments(node); emitStart(node); // variable declaration for import-equals declaration can be hoisted in system modules @@ -35579,7 +36040,7 @@ var ts; function getLocalNameForExternalImport(node) { var namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); + return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); } if (node.kind === 222 /* ImportDeclaration */ && node.importClause) { return getGeneratedNameForNode(node); @@ -35884,7 +36345,7 @@ var ts; ts.getEnclosingBlockScopeContainer(node).kind === 248 /* SourceFile */; } function isCurrentFileSystemExternalModule() { - return modulekind === 4 /* System */ && ts.isExternalModule(currentSourceFile); + return modulekind === 4 /* System */ && isCurrentFileExternalModule; } function emitSystemModuleBody(node, dependencyGroups, startIndex) { // shape of the body in system modules: @@ -36054,7 +36515,13 @@ var ts; writeLine(); write("}"); // execute } - function emitSystemModule(node) { + function writeModuleName(node, emitRelativePathAsModuleName) { + var moduleName = node.moduleName; + if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { + write("\"" + moduleName + "\", "); + } + } + function emitSystemModule(node, emitRelativePathAsModuleName) { collectExternalModuleInfo(node); // System modules has the following shape // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) @@ -36069,9 +36536,7 @@ var ts; exportFunctionForFile = makeUniqueName("exports"); writeLine(); write("System.register("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } + writeModuleName(node, emitRelativePathAsModuleName); write("["); var groupIndices = {}; var dependencyGroups = []; @@ -36090,6 +36555,12 @@ var ts; if (i !== 0) { write(", "); } + if (emitRelativePathAsModuleName) { + var name_29 = getExternalModuleNameFromDeclaration(host, resolver, externalImports[i]); + if (name_29) { + text = "\"" + name_29 + "\""; + } + } write(text); } write("], function(" + exportFunctionForFile + ") {"); @@ -36103,7 +36574,7 @@ var ts; writeLine(); write("});"); } - function getAMDDependencyNames(node, includeNonAmdDependencies) { + function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { // names of modules with corresponding parameter in the factory function var aliasedModuleNames = []; // names of modules with no corresponding parameters in factory function @@ -36126,6 +36597,12 @@ var ts; var importNode = externalImports_4[_c]; // Find the name of the external module var externalModuleName = getExternalModuleNameText(importNode); + if (emitRelativePathAsModuleName) { + var name_30 = getExternalModuleNameFromDeclaration(host, resolver, importNode); + if (name_30) { + externalModuleName = "\"" + name_30 + "\""; + } + } // Find the name of the module alias, if there is one var importAliasName = getLocalNameForExternalImport(importNode); if (includeNonAmdDependencies && importAliasName) { @@ -36138,7 +36615,7 @@ var ts; } return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies) { + function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { // An AMD define function has the following shape: // define(id?, dependencies?, factory); // @@ -36150,7 +36627,7 @@ var ts; // To ensure this is true in cases of modules with no aliases, e.g.: // `import "module"` or `` // we need to add modules without alias names to the end of the dependencies list - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies); + var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); emitAMDDependencyList(dependencyNames); write(", "); emitAMDFactoryHeader(dependencyNames); @@ -36177,15 +36654,13 @@ var ts; } write(") {"); } - function emitAMDModule(node) { + function emitAMDModule(node, emitRelativePathAsModuleName) { emitEmitHelpers(node); collectExternalModuleInfo(node); writeLine(); write("define("); - if (node.moduleName) { - write("\"" + node.moduleName + "\", "); - } - emitAMDDependencies(node, /*includeNonAmdDependencies*/ true); + writeModuleName(node, emitRelativePathAsModuleName); + emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, emitRelativePathAsModuleName); increaseIndent(); var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true); emitExportStarHelper(); @@ -36404,8 +36879,13 @@ var ts; emitShebang(); emitDetachedCommentsAndUpdateCommentsInfo(node); if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1 /* CommonJS */]; - emitModule(node); + if (root || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { + var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[1 /* CommonJS */]; + emitModule(node); + } + else { + bundleEmitDelegates[modulekind](node, /*emitRelativePathAsModuleName*/ true); + } } else { // emit prologue directives prior to __extends @@ -36666,7 +37146,7 @@ var ts; } function getLeadingCommentsWithoutDetachedComments() { // get the leading comments from detachedPos - var leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); + var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); } @@ -36683,10 +37163,10 @@ var ts; function isTripleSlashComment(comment) { // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text // so that we don't end up computing comment string and doing match for all // comments - if (currentSourceFile.text.charCodeAt(comment.pos + 1) === 47 /* slash */ && + if (currentText.charCodeAt(comment.pos + 1) === 47 /* slash */ && comment.pos + 2 < comment.end && - currentSourceFile.text.charCodeAt(comment.pos + 2) === 47 /* slash */) { - var textSubStr = currentSourceFile.text.substring(comment.pos, comment.end); + currentText.charCodeAt(comment.pos + 2) === 47 /* slash */) { + var textSubStr = currentText.substring(comment.pos, comment.end); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? true : false; @@ -36703,7 +37183,7 @@ var ts; } else { // get the leading comments from the node - return ts.getLeadingCommentRangesOfNode(node, currentSourceFile); + return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); } } } @@ -36712,7 +37192,7 @@ var ts; // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments if (node.parent) { if (node.parent.kind === 248 /* SourceFile */ || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentSourceFile.text, node.end); + return ts.getTrailingCommentRanges(currentText, node.end); } } } @@ -36746,9 +37226,9 @@ var ts; leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); } } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator:*/ true, newLine, writeComment); } function emitTrailingComments(node) { if (compilerOptions.removeComments) { @@ -36757,7 +37237,7 @@ var ts; // Emit the trailing comments only if the parent's end doesn't match var trailingComments = getTrailingCommentsToEmit(node); // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); } /** * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: @@ -36768,9 +37248,9 @@ var ts; if (compilerOptions.removeComments) { return; } - var trailingComments = ts.getTrailingCommentRanges(currentSourceFile.text, pos); + var trailingComments = ts.getTrailingCommentRanges(currentText, pos); // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); } function emitLeadingCommentsOfPositionWorker(pos) { if (compilerOptions.removeComments) { @@ -36783,14 +37263,14 @@ var ts; } else { // get the leading comments from the node - leadingComments = ts.getLeadingCommentRanges(currentSourceFile.text, pos); + leadingComments = ts.getLeadingCommentRanges(currentText, pos); } - ts.emitNewLineBeforeLeadingComments(currentSourceFile, writer, { pos: pos, end: pos }, leadingComments); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentSourceFile, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); + ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); } function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentSourceFile, writer, writeComment, node, newLine, compilerOptions.removeComments); + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -36801,12 +37281,12 @@ var ts; } } function emitShebang() { - var shebang = ts.getShebang(currentSourceFile.text); + var shebang = ts.getShebang(currentText); if (shebang) { write(shebang); } } - var _a; + var _a, _b; } function emitFile(jsFilePath, sourceFile) { emitJavaScript(jsFilePath, sourceFile); @@ -36866,11 +37346,11 @@ var ts; if (ts.getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { var failedLookupLocations = []; var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var resolvedFileName = loadNodeModuleFromFile(ts.supportedJsExtensions, candidate, failedLookupLocations, host); if (resolvedFileName) { return { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations }; } - resolvedFileName = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + resolvedFileName = loadNodeModuleFromDirectory(ts.supportedJsExtensions, candidate, failedLookupLocations, host); return resolvedFileName ? { resolvedModule: { resolvedFileName: resolvedFileName }, failedLookupLocations: failedLookupLocations } : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; @@ -36880,8 +37360,8 @@ var ts; } } ts.nodeModuleNameResolver = nodeModuleNameResolver; - function loadNodeModuleFromFile(candidate, failedLookupLocation, host) { - return ts.forEach(ts.moduleFileExtensions, tryLoad); + function loadNodeModuleFromFile(extensions, candidate, failedLookupLocation, host) { + return ts.forEach(extensions, tryLoad); function tryLoad(ext) { var fileName = ts.fileExtensionIs(candidate, ext) ? candidate : candidate + ext; if (host.fileExists(fileName)) { @@ -36893,7 +37373,7 @@ var ts; } } } - function loadNodeModuleFromDirectory(candidate, failedLookupLocation, host) { + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, host) { var packageJsonPath = ts.combinePaths(candidate, "package.json"); if (host.fileExists(packageJsonPath)) { var jsonContent; @@ -36906,7 +37386,7 @@ var ts; jsonContent = { typings: undefined }; } if (jsonContent.typings) { - var result = loadNodeModuleFromFile(ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); + var result = loadNodeModuleFromFile(extensions, ts.normalizePath(ts.combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); if (result) { return result; } @@ -36916,7 +37396,7 @@ var ts; // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocation.push(packageJsonPath); } - return loadNodeModuleFromFile(ts.combinePaths(candidate, "index"), failedLookupLocation, host); + return loadNodeModuleFromFile(extensions, ts.combinePaths(candidate, "index"), failedLookupLocation, host); } function loadModuleFromNodeModules(moduleName, directory, host) { var failedLookupLocations = []; @@ -36926,11 +37406,11 @@ var ts; if (baseName !== "node_modules") { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var result = loadNodeModuleFromFile(candidate, failedLookupLocations, host); + var result = loadNodeModuleFromFile(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } - result = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host); + result = loadNodeModuleFromDirectory(ts.supportedExtensions, candidate, failedLookupLocations, host); if (result) { return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations: failedLookupLocations }; } @@ -36956,9 +37436,10 @@ var ts; var searchName; var failedLookupLocations = []; var referencedSourceFile; + var extensions = compilerOptions.allowNonTsExtensions ? ts.supportedJsExtensions : ts.supportedExtensions; while (true) { searchName = ts.normalizePath(ts.combinePaths(searchPath, moduleName)); - referencedSourceFile = ts.forEach(ts.supportedExtensions, function (extension) { + referencedSourceFile = ts.forEach(extensions, function (extension) { if (extension === ".tsx" && !compilerOptions.jsx) { // resolve .tsx files only if jsx support is enabled // 'logical not' handles both undefined and None cases @@ -36989,10 +37470,8 @@ var ts; /* @internal */ ts.defaultInitCompilerOptions = { module: 1 /* CommonJS */, - target: 0 /* ES3 */, + target: 1 /* ES5 */, noImplicitAny: false, - outDir: "built", - rootDir: ".", sourceMap: false }; function createCompilerHost(options, setParentNodes) { @@ -37397,43 +37876,55 @@ var ts; if (file.imports) { return; } + var isJavaScriptFile = ts.isSourceFileJavaScript(file); var imports; for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collect(node, /* allowRelativeModuleNames */ true); + collect(node, /* allowRelativeModuleNames */ true, /* collectOnlyRequireCalls */ false); } file.imports = imports || emptyArray; - function collect(node, allowRelativeModuleNames) { - switch (node.kind) { - case 222 /* ImportDeclaration */: - case 221 /* ImportEqualsDeclaration */: - case 228 /* ExportDeclaration */: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + return; + function collect(node, allowRelativeModuleNames, collectOnlyRequireCalls) { + if (!collectOnlyRequireCalls) { + switch (node.kind) { + case 222 /* ImportDeclaration */: + case 221 /* ImportEqualsDeclaration */: + case 228 /* ExportDeclaration */: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + break; + } + if (!moduleNameExpr.text) { + break; + } + if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); + } break; - } - if (!moduleNameExpr.text) { - break; - } - if (allowRelativeModuleNames || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 218 /* ModuleDeclaration */: - if (node.name.kind === 9 /* StringLiteral */ && (node.flags & 4 /* Ambient */ || ts.isDeclarationFile(file))) { - // TypeScript 1.0 spec (April 2014): 12.1.6 - // An AmbientExternalModuleDeclaration declares an external module. - // This type of declaration is permitted only in the global module. - // The StringLiteral must specify a top - level external module name. - // Relative external module names are not permitted - ts.forEachChild(node.body, function (node) { + case 218 /* ModuleDeclaration */: + if (node.name.kind === 9 /* StringLiteral */ && (node.flags & 4 /* Ambient */ || ts.isDeclarationFile(file))) { // 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); - }); - } - break; + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + ts.forEachChild(node.body, function (node) { + // 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); + }); + } + break; + } + } + if (isJavaScriptFile) { + if (ts.isRequireCall(node)) { + (imports || (imports = [])).push(node.arguments[0]); + } + else { + ts.forEachChild(node, function (node) { return collect(node, allowRelativeModuleNames, /* collectOnlyRequireCalls */ true); }); + } } } } @@ -37526,7 +38017,6 @@ var ts; // always process imported modules to record module name resolutions processImportedModules(file, basePath); if (isDefaultLib) { - file.isDefaultLib = true; files.unshift(file); } else { @@ -37604,6 +38094,9 @@ var ts; commonPathComponents.length = sourcePathComponents.length; } }); + if (!commonPathComponents) { + return currentDirectory; + } return ts.getNormalizedPathFromPathComponents(commonPathComponents); } function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { @@ -37689,12 +38182,15 @@ var ts; if (options.module === 5 /* ES6 */ && languageVersion < 2 /* ES6 */) { programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower)); } + // Cannot specify module gen that isn't amd or system with --out + if (outFile && options.module && !(options.module === 2 /* AMD */ || options.module === 4 /* System */)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } // there has to be common source directory if user specified --outdir || --sourceRoot // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted if (options.outDir || options.sourceRoot || - (options.mapRoot && - (!outFile || firstExternalModuleSourceFile !== undefined))) { + options.mapRoot) { if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { // If a rootDir is specified and is valid use it as the commonSourceDirectory commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); @@ -38212,20 +38708,20 @@ var ts; var exclude = json["exclude"] instanceof Array ? ts.map(json["exclude"], ts.normalizeSlashes) : undefined; var sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); for (var i = 0; i < sysFiles.length; i++) { - var name_29 = sysFiles[i]; - if (ts.fileExtensionIs(name_29, ".d.ts")) { - var baseName = name_29.substr(0, name_29.length - ".d.ts".length); + var name_31 = sysFiles[i]; + if (ts.fileExtensionIs(name_31, ".d.ts")) { + var baseName = name_31.substr(0, name_31.length - ".d.ts".length); if (!ts.contains(sysFiles, baseName + ".tsx") && !ts.contains(sysFiles, baseName + ".ts")) { - fileNames.push(name_29); + fileNames.push(name_31); } } - else if (ts.fileExtensionIs(name_29, ".ts")) { - if (!ts.contains(sysFiles, name_29 + "x")) { - fileNames.push(name_29); + else if (ts.fileExtensionIs(name_31, ".ts")) { + if (!ts.contains(sysFiles, name_31 + "x")) { + fileNames.push(name_31); } } else { - fileNames.push(name_29); + fileNames.push(name_31); } } } @@ -38453,12 +38949,12 @@ var ts; ts.forEach(program.getSourceFiles(), function (sourceFile) { cancellationToken.throwIfCancellationRequested(); var nameToDeclarations = sourceFile.getNamedDeclarations(); - for (var name_30 in nameToDeclarations) { - var declarations = ts.getProperty(nameToDeclarations, name_30); + for (var name_32 in nameToDeclarations) { + var declarations = ts.getProperty(nameToDeclarations, name_32); if (declarations) { // First do a quick check to see if the name of the declaration matches the // last portion of the (possibly) dotted name they're searching for. - var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_30); + var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_32); if (!matches) { continue; } @@ -38471,14 +38967,14 @@ var ts; if (!containers) { return undefined; } - matches = patternMatcher.getMatches(containers, name_30); + matches = patternMatcher.getMatches(containers, name_32); if (!matches) { continue; } } var fileName = sourceFile.fileName; var matchKind = bestMatchKind(matches); - rawItems.push({ name: name_30, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); + rawItems.push({ name: name_32, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); } } } @@ -38859,9 +39355,9 @@ var ts; case 211 /* VariableDeclaration */: case 163 /* BindingElement */: var variableDeclarationNode; - var name_31; + var name_33; if (node.kind === 163 /* BindingElement */) { - name_31 = node.name; + name_33 = node.name; variableDeclarationNode = node; // binding elements are added only for variable declarations // bubble up to the containing variable declaration @@ -38873,16 +39369,16 @@ var ts; else { ts.Debug.assert(!ts.isBindingPattern(node.name)); variableDeclarationNode = node; - name_31 = node.name; + name_33 = node.name; } if (ts.isConst(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.constElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.constElement); } else if (ts.isLet(variableDeclarationNode)) { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.letElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.letElement); } else { - return createItem(node, getTextOfNode(name_31), ts.ScriptElementKind.variableElement); + return createItem(node, getTextOfNode(name_33), ts.ScriptElementKind.variableElement); } case 144 /* Constructor */: return createItem(node, "constructor", ts.ScriptElementKind.constructorImplementationElement); @@ -39802,7 +40298,7 @@ var ts; if (!candidates.length) { // We didn't have any sig help items produced by the TS compiler. If this is a JS // file, then see if we can figure out anything better. - if (ts.isJavaScript(sourceFile.fileName)) { + if (ts.isSourceFileJavaScript(sourceFile)) { return createJavaScriptSignatureHelpItems(argumentInfo); } return undefined; @@ -41662,9 +42158,9 @@ var ts; } Rules.prototype.getRuleName = function (rule) { var o = this; - for (var name_32 in o) { - if (o[name_32] === rule) { - return name_32; + for (var name_34 in o) { + if (o[name_34] === rule) { + return name_34; } } throw new Error("Unknown rule"); @@ -42096,7 +42592,7 @@ var ts; function TokenRangeAccess(from, to, except) { this.tokens = []; for (var token = from; token <= to; token++) { - if (except.indexOf(token) < 0) { + if (ts.indexOf(except, token) < 0) { this.tokens.push(token); } } @@ -43709,13 +44205,18 @@ var ts; ]; var jsDocCompletionEntries; function createNode(kind, pos, end, flags, parent) { - var node = new (ts.getNodeConstructor(kind))(pos, end); + var node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; } var NodeObject = (function () { - function NodeObject() { + function NodeObject(kind, pos, end) { + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; } NodeObject.prototype.getSourceFile = function () { return ts.getSourceFileOfNode(this); @@ -44198,8 +44699,8 @@ var ts; })(); var SourceFileObject = (function (_super) { __extends(SourceFileObject, _super); - function SourceFileObject() { - _super.apply(this, arguments); + function SourceFileObject(kind, pos, end) { + _super.call(this, kind, pos, end); } SourceFileObject.prototype.update = function (newText, textChangeRange) { return ts.updateSourceFile(this, newText, textChangeRange); @@ -44521,6 +45022,9 @@ var ts; ClassificationTypeNames.typeAliasName = "type alias name"; ClassificationTypeNames.parameterName = "parameter name"; ClassificationTypeNames.docCommentTagName = "doc comment tag name"; + ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; + ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; + ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; return ClassificationTypeNames; })(); ts.ClassificationTypeNames = ClassificationTypeNames; @@ -44543,6 +45047,9 @@ var ts; ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; + ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; + ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; + ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; })(ts.ClassificationType || (ts.ClassificationType = {})); var ClassificationType = ts.ClassificationType; function displayPartsToString(displayParts) { @@ -44922,8 +45429,9 @@ var ts; }; } ts.createDocumentRegistry = createDocumentRegistry; - function preProcessFile(sourceText, readImportFiles) { + function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) { if (readImportFiles === void 0) { readImportFiles = true; } + if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } var referencedFiles = []; var importedFiles = []; var ambientExternalModules; @@ -44957,9 +45465,207 @@ var ts; end: pos + importPath.length }); } - function processImport() { + /** + * Returns true if at least one token was consumed from the stream + */ + function tryConsumeDeclare() { + var token = scanner.getToken(); + if (token === 122 /* DeclareKeyword */) { + // declare module "mod" + token = scanner.scan(); + if (token === 125 /* ModuleKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + recordAmbientExternalModule(); + } + } + return true; + } + return false; + } + /** + * Returns true if at least one token was consumed from the stream + */ + function tryConsumeImport() { + var token = scanner.getToken(); + if (token === 89 /* ImportKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import "mod"; + recordModuleName(); + return true; + } + else { + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import d from "mod"; + recordModuleName(); + return true; + } + } + else if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + return true; + } + } + else if (token === 24 /* CommaToken */) { + // consume comma and keep going + token = scanner.scan(); + } + else { + // unknown syntax + return true; + } + } + if (token === 15 /* OpenBraceToken */) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + // make sure that it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = scanner.scan(); + } + if (token === 16 /* CloseBraceToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import {a as A} from "mod"; + // import d, {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = scanner.scan(); + if (token === 116 /* AsKeyword */) { + token = scanner.scan(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // import * as NS from "mod" + // import d, * as NS from "mod" + recordModuleName(); + } + } + } + } + } + } + return true; + } + return false; + } + function tryConsumeExport() { + var token = scanner.getToken(); + if (token === 82 /* ExportKeyword */) { + token = scanner.scan(); + if (token === 15 /* OpenBraceToken */) { + token = scanner.scan(); + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = scanner.scan(); + } + if (token === 16 /* CloseBraceToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = scanner.scan(); + if (token === 133 /* FromKeyword */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // export * from "mod" + recordModuleName(); + } + } + } + else if (token === 89 /* ImportKeyword */) { + token = scanner.scan(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = scanner.scan(); + if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + return true; + } + } + } + } + return true; + } + return false; + } + function tryConsumeRequireCall(skipCurrentToken) { + var token = skipCurrentToken ? scanner.scan() : scanner.getToken(); + if (token === 127 /* RequireKeyword */) { + token = scanner.scan(); + if (token === 17 /* OpenParenToken */) { + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // require("mod"); + recordModuleName(); + } + } + return true; + } + return false; + } + function tryConsumeDefine() { + var token = scanner.getToken(); + if (token === 69 /* Identifier */ && scanner.getTokenValue() === "define") { + token = scanner.scan(); + if (token !== 17 /* OpenParenToken */) { + return true; + } + token = scanner.scan(); + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma + token = scanner.scan(); + if (token === 24 /* CommaToken */) { + token = scanner.scan(); + } + else { + // unexpected token + return true; + } + } + // should be start of dependency list + if (token !== 19 /* OpenBracketToken */) { + return true; + } + // skip open bracket + token = scanner.scan(); + var i = 0; + // scan until ']' or EOF + while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { + recordModuleName(); + i++; + } + token = scanner.scan(); + } + return true; + } + return false; + } + function processImports() { scanner.setText(sourceText); - var token = scanner.scan(); + scanner.scan(); // Look for: // import "mod"; // import d from "mod" @@ -44971,152 +45677,26 @@ var ts; // export * from "mod" // export {a as b} from "mod" // export import i = require("mod") - while (token !== 1 /* EndOfFileToken */) { - if (token === 122 /* DeclareKeyword */) { - // declare module "mod" - token = scanner.scan(); - if (token === 125 /* ModuleKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - recordAmbientExternalModule(); - continue; - } - } + // (for JavaScript files) require("mod") + while (true) { + if (scanner.getToken() === 1 /* EndOfFileToken */) { + break; } - else if (token === 89 /* ImportKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import "mod"; - recordModuleName(); - continue; - } - else { - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import d from "mod"; - recordModuleName(); - continue; - } - } - else if (token === 56 /* EqualsToken */) { - token = scanner.scan(); - if (token === 127 /* RequireKeyword */) { - token = scanner.scan(); - if (token === 17 /* OpenParenToken */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import i = require("mod"); - recordModuleName(); - continue; - } - } - } - } - else if (token === 24 /* CommaToken */) { - // consume comma and keep going - token = scanner.scan(); - } - else { - // unknown syntax - continue; - } - } - if (token === 15 /* OpenBraceToken */) { - token = scanner.scan(); - // consume "{ a as B, c, d as D}" clauses - while (token !== 16 /* CloseBraceToken */) { - token = scanner.scan(); - } - if (token === 16 /* CloseBraceToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import {a as A} from "mod"; - // import d, {a, b as B} from "mod" - recordModuleName(); - } - } - } - } - else if (token === 37 /* AsteriskToken */) { - token = scanner.scan(); - if (token === 116 /* AsKeyword */) { - token = scanner.scan(); - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // import * as NS from "mod" - // import d, * as NS from "mod" - recordModuleName(); - } - } - } - } - } - } + // check if at least one of alternative have moved scanner forward + if (tryConsumeDeclare() || + tryConsumeImport() || + tryConsumeExport() || + (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + continue; } - else if (token === 82 /* ExportKeyword */) { - token = scanner.scan(); - if (token === 15 /* OpenBraceToken */) { - token = scanner.scan(); - // consume "{ a as B, c, d as D}" clauses - while (token !== 16 /* CloseBraceToken */) { - token = scanner.scan(); - } - if (token === 16 /* CloseBraceToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export {a as A} from "mod"; - // export {a, b as B} from "mod" - recordModuleName(); - } - } - } - } - else if (token === 37 /* AsteriskToken */) { - token = scanner.scan(); - if (token === 133 /* FromKeyword */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export * from "mod" - recordModuleName(); - } - } - } - else if (token === 89 /* ImportKeyword */) { - token = scanner.scan(); - if (token === 69 /* Identifier */ || ts.isKeyword(token)) { - token = scanner.scan(); - if (token === 56 /* EqualsToken */) { - token = scanner.scan(); - if (token === 127 /* RequireKeyword */) { - token = scanner.scan(); - if (token === 17 /* OpenParenToken */) { - token = scanner.scan(); - if (token === 9 /* StringLiteral */) { - // export import i = require("mod"); - recordModuleName(); - } - } - } - } - } - } + else { + scanner.scan(); } - token = scanner.scan(); } scanner.setText(undefined); } if (readImportFiles) { - processImport(); + processImports(); } processTripleSlashDirectives(); return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientExternalModules }; @@ -45547,7 +46127,7 @@ var ts; // For JavaScript files, we don't want to report the normal typescript semantic errors. // Instead, we just report errors for using TypeScript-only constructs from within a // JavaScript file. - if (ts.isJavaScript(fileName)) { + if (ts.isSourceFileJavaScript(targetSourceFile)) { return getJavaScriptSemanticDiagnostics(targetSourceFile); } // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. @@ -45759,7 +46339,7 @@ var ts; var typeChecker = program.getTypeChecker(); var syntacticStart = new Date().getTime(); var sourceFile = getValidSourceFile(fileName); - var isJavaScriptFile = ts.isJavaScript(fileName); + var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); var isJsDocTagName = false; var start = new Date().getTime(); var currentToken = ts.getTokenAtPosition(sourceFile, position); @@ -46393,8 +46973,8 @@ var ts; if (element.getStart() <= position && position <= element.getEnd()) { continue; } - var name_33 = element.propertyName || element.name; - exisingImportsOrExports[name_33.text] = true; + var name_35 = element.propertyName || element.name; + exisingImportsOrExports[name_35.text] = true; } if (ts.isEmpty(exisingImportsOrExports)) { return exportsOfModule; @@ -46426,7 +47006,10 @@ var ts; } var existingName = void 0; if (m.kind === 163 /* BindingElement */ && m.propertyName) { - existingName = m.propertyName.text; + // include only identifiers in completion list + if (m.propertyName.kind === 69 /* Identifier */) { + existingName = m.propertyName.text; + } } else { // TODO(jfreeman): Account for computed property name @@ -46466,46 +47049,43 @@ var ts; return undefined; } var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isRightOfDot = completionData.isRightOfDot, isJsDocTagName = completionData.isJsDocTagName; - var entries; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - if (isRightOfDot && ts.isJavaScript(fileName)) { - entries = getCompletionEntriesFromSymbols(symbols); - ts.addRange(entries, getJavaScriptCompletionEntries()); + var sourceFile = getValidSourceFile(fileName); + var entries = []; + if (isRightOfDot && ts.isSourceFileJavaScript(sourceFile)) { + var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); + ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, uniqueNames)); } else { if (!symbols || symbols.length === 0) { return undefined; } - entries = getCompletionEntriesFromSymbols(symbols); + getCompletionEntriesFromSymbols(symbols, entries); } // Add keywords if this is not a member completion list if (!isMemberCompletion && !isJsDocTagName) { ts.addRange(entries, keywordCompletions); } return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries }; - function getJavaScriptCompletionEntries() { + function getJavaScriptCompletionEntries(sourceFile, uniqueNames) { var entries = []; - var allNames = {}; var target = program.getCompilerOptions().target; - for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { - var sourceFile = _a[_i]; - var nameTable = getNameTable(sourceFile); - for (var name_34 in nameTable) { - if (!allNames[name_34]) { - allNames[name_34] = name_34; - var displayName = getCompletionEntryDisplayName(name_34, target, /*performCharacterChecks:*/ true); - if (displayName) { - var entry = { - name: displayName, - kind: ScriptElementKind.warning, - kindModifiers: "", - sortText: "1" - }; - entries.push(entry); - } + var nameTable = getNameTable(sourceFile); + for (var name_36 in nameTable) { + if (!uniqueNames[name_36]) { + uniqueNames[name_36] = name_36; + var displayName = getCompletionEntryDisplayName(name_36, target, /*performCharacterChecks:*/ true); + if (displayName) { + var entry = { + name: displayName, + kind: ScriptElementKind.warning, + kindModifiers: "", + sortText: "1" + }; + entries.push(entry); } } } @@ -46543,25 +47123,24 @@ var ts; sortText: "0" }; } - function getCompletionEntriesFromSymbols(symbols) { + function getCompletionEntriesFromSymbols(symbols, entries) { var start = new Date().getTime(); - var entries = []; + var uniqueNames = {}; if (symbols) { - var nameToSymbol = {}; for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) { var symbol = symbols_3[_i]; var entry = createCompletionEntry(symbol, location); if (entry) { var id = ts.escapeIdentifier(entry.name); - if (!ts.lookUp(nameToSymbol, id)) { + if (!ts.lookUp(uniqueNames, id)) { entries.push(entry); - nameToSymbol[id] = symbol; + uniqueNames[id] = id; } } } } log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start)); - return entries; + return uniqueNames; } } function getCompletionEntryDetails(fileName, position, entryName) { @@ -46762,16 +47341,16 @@ var ts; case ScriptElementKind.parameterElement: case ScriptElementKind.localVariableElement: // If it is call or construct signature of lambda's write type name - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.punctuationPart(ts.SyntaxKind.ColonToken)); displayParts.push(ts.spacePart()); if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); displayParts.push(ts.spacePart()); } - if (!(type.flags & 65536 /* Anonymous */)) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); + if (!(type.flags & ts.TypeFlags.Anonymous)) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, ts.SymbolFormatFlags.WriteTypeParametersOrArguments)); } - addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); + addSignatureDisplayParts(signature, allSignatures, ts.TypeFormatFlags.WriteArrowStyleSignature); break; default: // Just signature @@ -48396,19 +48975,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_35 = node.text; + var name_37 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_35); + var unionProperty = contextualType.getProperty(name_37); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_35); + var symbol = t.getProperty(name_37); if (symbol) { result_4.push(symbol); } @@ -48417,7 +48996,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_35); + var symbol_1 = contextualType.getProperty(name_37); if (symbol_1) { return [symbol_1]; } @@ -48828,6 +49407,9 @@ var ts; case 16 /* typeAliasName */: return ClassificationTypeNames.typeAliasName; case 17 /* parameterName */: return ClassificationTypeNames.parameterName; case 18 /* docCommentTagName */: return ClassificationTypeNames.docCommentTagName; + case 19 /* jsxOpenTagName */: return ClassificationTypeNames.jsxOpenTagName; + case 20 /* jsxCloseTagName */: return ClassificationTypeNames.jsxCloseTagName; + case 21 /* jsxSelfClosingTagName */: return ClassificationTypeNames.jsxSelfClosingTagName; } } function convertClassifications(classifications) { @@ -49097,6 +49679,21 @@ var ts; return 17 /* parameterName */; } return; + case 235 /* JsxOpeningElement */: + if (token.parent.tagName === token) { + return 19 /* jsxOpenTagName */; + } + return; + case 237 /* JsxClosingElement */: + if (token.parent.tagName === token) { + return 20 /* jsxCloseTagName */; + } + return; + case 234 /* JsxSelfClosingElement */: + if (token.parent.tagName === token) { + return 21 /* jsxSelfClosingTagName */; + } + return; } } return 2 /* identifier */; @@ -50021,18 +50618,8 @@ var ts; ts.getDefaultLibFilePath = getDefaultLibFilePath; function initializeServices() { ts.objectAllocator = { - getNodeConstructor: function (kind) { - function Node(pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - } - var proto = kind === 248 /* SourceFile */ ? new SourceFileObject() : new NodeObject(); - proto.kind = kind; - Node.prototype = proto; - return Node; - }, + getNodeConstructor: function () { return NodeObject; }, + getSourceFileConstructor: function () { return SourceFileObject; }, getSymbolConstructor: function () { return SymbolObject; }, getTypeConstructor: function () { return TypeObject; }, getSignatureConstructor: function () { return SignatureObject; } @@ -51102,7 +51689,8 @@ var ts; }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { - var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength())); + // for now treat files as JavaScript + var result = ts.preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true); var convertResult = { referencedFiles: [], importedFiles: [], @@ -51166,7 +51754,7 @@ var ts; TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) { try { if (this.documentRegistry === undefined) { - this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry); @@ -51199,7 +51787,7 @@ var ts; TypeScriptServicesFactory.prototype.close = function () { // Forget all the registered shims this._shims = []; - this.documentRegistry = ts.createDocumentRegistry(); + this.documentRegistry = undefined; }; TypeScriptServicesFactory.prototype.registerShim = function (shim) { this._shims.push(shim); From 527f4658ad71135ee2a5d7bf441d3c84fdfa7aeb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 11 Nov 2015 11:39:46 -0800 Subject: [PATCH 42/93] Use string literal types in the command line parser. --- src/compiler/types.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8b0027c1377..5f9f82d9a64 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2179,17 +2179,17 @@ namespace ts { /* @internal */ export interface CommandLineOptionBase { name: string; - type: string | Map; // "string", "number", "boolean", or an object literal mapping named values to actual values - isFilePath?: boolean; // True if option value is a path or fileName - shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' - description?: DiagnosticMessage; // The message describing what the command line switch does - paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter + type: "string" | "number" | "boolean" | Map; // a value of a primitive type, or an object literal mapping named values to actual values + isFilePath?: boolean; // True if option value is a path or fileName + shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' + description?: DiagnosticMessage; // The message describing what the command line switch does + paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter experimental?: boolean; } /* @internal */ export interface CommandLineOptionOfPrimitiveType extends CommandLineOptionBase { - type: string; // "string" | "number" | "boolean" + type: "string" | "number" | "boolean"; } /* @internal */ From 593ba66af107602b33bd4db1da8011aebce4a43d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Nov 2015 14:35:30 -0800 Subject: [PATCH 43/93] 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 44/93] 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 45/93] 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 46/93] 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 47/93] 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 48/93] 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 6c29ddf16203b0bd7a88081596c061a346455106 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 15:30:09 -0800 Subject: [PATCH 49/93] loosen walk up containers, add extra test --- src/compiler/checker.ts | 8 +--- tests/baselines/reference/typeGuardInClass.js | 37 +++++++++++++++++++ .../reference/typeGuardInClass.symbols | 27 ++++++++++++++ .../reference/typeGuardInClass.types | 32 ++++++++++++++++ .../typeGuardsInFunctionAndModuleBlock.js | 8 ++-- ...typeGuardsInFunctionAndModuleBlock.symbols | 4 +- .../typeGuardsInFunctionAndModuleBlock.types | 8 ++-- .../typeGuards/typeGuardInClass.ts | 16 ++++++++ .../typeGuardsInFunctionAndModuleBlock.ts | 4 +- 9 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 tests/baselines/reference/typeGuardInClass.js create mode 100644 tests/baselines/reference/typeGuardInClass.symbols create mode 100644 tests/baselines/reference/typeGuardInClass.types create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7856e3f4cda..615d6f1834c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6399,13 +6399,7 @@ namespace ts { break; case SyntaxKind.SourceFile: case SyntaxKind.ModuleDeclaration: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.Constructor: - // Stop at the first containing function or module declaration + // Stop at the first containing file or module declaration break loop; } } diff --git a/tests/baselines/reference/typeGuardInClass.js b/tests/baselines/reference/typeGuardInClass.js new file mode 100644 index 00000000000..44bda9f4cb5 --- /dev/null +++ b/tests/baselines/reference/typeGuardInClass.js @@ -0,0 +1,37 @@ +//// [typeGuardInClass.ts] +let x: string | number; + +if (typeof x === "string") { + let n = class { + constructor() { + x; // Should be "string" + } + } +} +else { + let m = class { + constructor() { + x; // Should be "number" + } + } +} + + +//// [typeGuardInClass.js] +var x; +if (typeof x === "string") { + var n = (function () { + function class_1() { + x; // Should be "string" + } + return class_1; + })(); +} +else { + var m = (function () { + function class_2() { + x; // Should be "number" + } + return class_2; + })(); +} diff --git a/tests/baselines/reference/typeGuardInClass.symbols b/tests/baselines/reference/typeGuardInClass.symbols new file mode 100644 index 00000000000..66de1651859 --- /dev/null +++ b/tests/baselines/reference/typeGuardInClass.symbols @@ -0,0 +1,27 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts === +let x: string | number; +>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) + +if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) + + let n = class { +>n : Symbol(n, Decl(typeGuardInClass.ts, 3, 7)) + + constructor() { + x; // Should be "string" +>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) + } + } +} +else { + let m = class { +>m : Symbol(m, Decl(typeGuardInClass.ts, 10, 7)) + + constructor() { + x; // Should be "number" +>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) + } + } +} + diff --git a/tests/baselines/reference/typeGuardInClass.types b/tests/baselines/reference/typeGuardInClass.types new file mode 100644 index 00000000000..8552b58508e --- /dev/null +++ b/tests/baselines/reference/typeGuardInClass.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts === +let x: string | number; +>x : string | number + +if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : string | number +>"string" : string + + let n = class { +>n : typeof (Anonymous class) +>class { constructor() { x; // Should be "string" } } : typeof (Anonymous class) + + constructor() { + x; // Should be "string" +>x : string + } + } +} +else { + let m = class { +>m : typeof (Anonymous class) +>class { constructor() { x; // Should be "number" } } : typeof (Anonymous class) + + constructor() { + x; // Should be "number" +>x : number + } + } +} + diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.js b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.js index 7cf19dac0ad..91443a9ae78 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.js +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.js @@ -41,12 +41,12 @@ function foo4(x: number | string | boolean) { : x.toString(); // number })(x); // x here is narrowed to number | boolean } -// Type guards affect nested function expressions, but not nested function declarations +// Type guards affect nested function expressions and nested function declarations function foo5(x: number | string | boolean) { if (typeof x === "string") { var y = x; // string; function foo() { - var z = x; // number | string | boolean, type guard has no effect + var z = x; // string } } } @@ -121,12 +121,12 @@ function foo4(x) { : x.toString(); // number })(x); // x here is narrowed to number | boolean } -// Type guards affect nested function expressions, but not nested function declarations +// Type guards affect nested function expressions and nested function declarations function foo5(x) { if (typeof x === "string") { var y = x; // string; function foo() { - var z = x; // number | string | boolean, type guard has no effect + var z = x; // string } } } diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols index 2f3232b0225..34810f303db 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols @@ -130,7 +130,7 @@ function foo4(x: number | string | boolean) { })(x); // x here is narrowed to number | boolean >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 32, 14)) } -// Type guards affect nested function expressions, but not nested function declarations +// Type guards affect nested function expressions and nested function declarations function foo5(x: number | string | boolean) { >foo5 : Symbol(foo5, Decl(typeGuardsInFunctionAndModuleBlock.ts, 41, 1)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 43, 14)) @@ -145,7 +145,7 @@ function foo5(x: number | string | boolean) { function foo() { >foo : Symbol(foo, Decl(typeGuardsInFunctionAndModuleBlock.ts, 45, 18)) - var z = x; // number | string | boolean, type guard has no effect + var z = x; // string >z : Symbol(z, Decl(typeGuardsInFunctionAndModuleBlock.ts, 47, 15)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 43, 14)) } diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types index 0a084d6eb54..f7d56ed17d1 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types @@ -181,7 +181,7 @@ function foo4(x: number | string | boolean) { })(x); // x here is narrowed to number | boolean >x : number | boolean } -// Type guards affect nested function expressions, but not nested function declarations +// Type guards affect nested function expressions and nested function declarations function foo5(x: number | string | boolean) { >foo5 : (x: number | string | boolean) => void >x : number | string | boolean @@ -199,9 +199,9 @@ function foo5(x: number | string | boolean) { function foo() { >foo : () => void - var z = x; // number | string | boolean, type guard has no effect ->z : number | string | boolean ->x : number | string | boolean + var z = x; // string +>z : string +>x : string } } } diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts new file mode 100644 index 00000000000..f88088744fc --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts @@ -0,0 +1,16 @@ +let x: string | number; + +if (typeof x === "string") { + let n = class { + constructor() { + x; // Should be "string" + } + } +} +else { + let m = class { + constructor() { + x; // Should be "number" + } + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardsInFunctionAndModuleBlock.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardsInFunctionAndModuleBlock.ts index ec23b75b590..5dbc925d04b 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardsInFunctionAndModuleBlock.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardsInFunctionAndModuleBlock.ts @@ -40,12 +40,12 @@ function foo4(x: number | string | boolean) { : x.toString(); // number })(x); // x here is narrowed to number | boolean } -// Type guards affect nested function expressions, but not nested function declarations +// Type guards affect nested function expressions and nested function declarations function foo5(x: number | string | boolean) { if (typeof x === "string") { var y = x; // string; function foo() { - var z = x; // number | string | boolean, type guard has no effect + var z = x; // string } } } From 472afc4e16771cf94d71b77b02a507fefd6c8651 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Nov 2015 15:48:41 -0800 Subject: [PATCH 50/93] add condition to bail at containing level --- src/compiler/checker.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 615d6f1834c..2eaf91b9614 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6386,6 +6386,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)) { + const declaration = getDeclarationOfKind(symbol, SyntaxKind.VariableDeclaration); + const top = declaration && getDeclarationContainer(declaration); const originalType = type; const nodeStack: {node: Node, child: Node}[] = []; loop: while (node.parent) { @@ -6402,6 +6404,9 @@ namespace ts { // Stop at the first containing file or module declaration break loop; } + if (node === top) { + break; + } } let nodes: {node: Node, child: Node}; From 4720c3592df77ac0be3cef7e427e5ea4d0804f84 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 11 Nov 2015 16:51:29 -0800 Subject: [PATCH 51/93] 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 52/93] 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 53/93] 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 54/93] 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 55/93] 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 56/93] 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 57/93] 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 58/93] 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 59/93] 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 60/93] 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 b24f8f35b762e6239454f4ab7431c2ab57086e43 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 12 Nov 2015 14:09:51 -0800 Subject: [PATCH 61/93] go go go --- tests/cases/compiler/commonSourceDir3.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cases/compiler/commonSourceDir3.ts b/tests/cases/compiler/commonSourceDir3.ts index cc42eb8f267..54b6e8c89b7 100644 --- a/tests/cases/compiler/commonSourceDir3.ts +++ b/tests/cases/compiler/commonSourceDir3.ts @@ -1,3 +1,4 @@ +// @useCaseSensitiveFileNames: false // @outDir: A:/ // @Filename: A:/foo/bar.ts var x: number; From 986d8845029fa0eb9b52b61e270b7c87501ba25e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Nov 2015 14:13:35 -0800 Subject: [PATCH 62/93] 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 63/93] 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 5bcf8611210e5e988bb6317def16389a71b2074c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 12 Nov 2015 15:58:11 -0800 Subject: [PATCH 64/93] use relative path from current directory --- src/compiler/program.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 3981d5a2421..28c51ce2f3a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -947,7 +947,9 @@ namespace ts { return currentDirectory; } - return getNormalizedPathFromPathComponents(commonPathComponents); + const path = getNormalizedPathFromPathComponents(commonPathComponents); + const relativePath = convertToRelativePath(path, currentDirectory, getCanonicalFileName); + return relativePath; } function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { From ecd4435986be2e0e2ff9492ca524a2af7f2ebf02 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 12 Nov 2015 16:22:35 -0800 Subject: [PATCH 65/93] Go all the way back to the original solution --- src/compiler/program.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 3fb432d9668..1f0096e7f6e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -910,7 +910,7 @@ namespace ts { return; } - const sourcePathComponents = getNormalizedPathComponents(getCanonicalFileName(sourceFile.fileName), currentDirectory); + const sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory); sourcePathComponents.pop(); // The base file name is not part of the common directory path if (!commonPathComponents) { @@ -919,8 +919,9 @@ namespace ts { return; } + const caseSensitive = host.useCaseSensitiveFileNames(); for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (commonPathComponents[i] !== sourcePathComponents[i]) { + if (caseSensitive ? commonPathComponents[i] !== sourcePathComponents[i] : commonPathComponents[i].toLocaleLowerCase() !== sourcePathComponents[i].toLocaleLowerCase()) { if (i === 0) { // Failed to find any common path component return true; @@ -947,9 +948,7 @@ namespace ts { return currentDirectory; } - const path = getNormalizedPathFromPathComponents(commonPathComponents); - const relativePath = convertToRelativePath(path, currentDirectory, getCanonicalFileName); - return relativePath; + return getNormalizedPathFromPathComponents(commonPathComponents); } function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { From 346253a0d520e24083ab013d247b986cc9b63db9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 11:13:10 -0800 Subject: [PATCH 66/93] 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 67/93] 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 68/93] 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 69/93] 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 70/93] 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 71/93] 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 72/93] 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 ff95731507bcf831f7339d25f72c37cc6c12fdd4 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 16:49:16 -0800 Subject: [PATCH 73/93] :S --- src/harness/compilerRunner.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 0785faccdf2..16616505c4e 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -50,9 +50,8 @@ class CompilerBaselineRunner extends RunnerBase { // Everything declared here should be cleared out in the "after" callback. let justName: string; - let tcSettings: Harness.TestCaseParser.CompilerSettings; - let lastUnit: Harness.TestCaseParser.TestUnitData; + let tcSettings: Harness.TestCaseParser.CompilerSettings; let result: Harness.Compiler.CompilerResult; let program: ts.Program; @@ -67,7 +66,7 @@ class CompilerBaselineRunner extends RunnerBase { const content = Harness.IO.readFile(fileName); const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); const units = testCaseContent.testUnitData; - harnessSettings = testCaseContent.settings; + const tcSettings = testCaseContent.settings; lastUnit = units[units.length - 1]; const rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; // 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) @@ -90,7 +89,7 @@ class CompilerBaselineRunner extends RunnerBase { } const output = Harness.Compiler.HarnessCompiler.compileFiles( - toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined); + toBeCompiled, otherFiles, tcSettings, /* options */ undefined, /* currentDirectory */ undefined); options = output.options; result = output.result; @@ -101,7 +100,6 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. justName = undefined; - harnessSettings = undefined; lastUnit = undefined; result = undefined; program = undefined; @@ -178,7 +176,7 @@ class CompilerBaselineRunner extends RunnerBase { const declFileCompilationResult = Harness.Compiler.HarnessCompiler.compileDeclarationFiles( - toBeCompiled, otherFiles, result, harnessSettings, options, /* currentDirectory */ undefined); + toBeCompiled, otherFiles, result, tcSettings, options, /* currentDirectory */ undefined); if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) { jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n"; From bfdb2d0fc98a2966b3564dde62860f93d87f0dac Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 16:57:17 -0800 Subject: [PATCH 74/93] and somehow all that caused was a lint error --- src/harness/compilerRunner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 16616505c4e..dbe22beabcf 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -66,7 +66,7 @@ class CompilerBaselineRunner extends RunnerBase { const content = Harness.IO.readFile(fileName); const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); const units = testCaseContent.testUnitData; - const tcSettings = testCaseContent.settings; + tcSettings = testCaseContent.settings; lastUnit = units[units.length - 1]; const rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; // 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) From e41bfd1ccc753957b94b252ef62b98b011a99d0e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 13 Nov 2015 17:43:53 -0800 Subject: [PATCH 75/93] 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); From e49e55287a3b205ffa263b6fc58fa59fa8395e7b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 14 Nov 2015 12:08:47 -0800 Subject: [PATCH 76/93] do not crash when variable and function declarations collide --- src/compiler/checker.ts | 6 ++++-- .../reference/nonMergedOverloads.errors.txt | 20 +++++++++++++++++++ .../baselines/reference/nonMergedOverloads.js | 12 +++++++++++ tests/cases/compiler/nonMergedOverloads.ts | 5 +++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/nonMergedOverloads.errors.txt create mode 100644 tests/baselines/reference/nonMergedOverloads.js create mode 100644 tests/cases/compiler/nonMergedOverloads.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f5f73a58db..f975c110b03 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11360,12 +11360,14 @@ 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) { - Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature); + const reportError = + (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && + (node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static); // 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)) { + if (reportError) { const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; error(errorNode, diagnostic); } diff --git a/tests/baselines/reference/nonMergedOverloads.errors.txt b/tests/baselines/reference/nonMergedOverloads.errors.txt new file mode 100644 index 00000000000..9a38ebdc3b3 --- /dev/null +++ b/tests/baselines/reference/nonMergedOverloads.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/nonMergedOverloads.ts(1,5): error TS2300: Duplicate identifier 'f'. +tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS1148: Cannot compile modules unless the '--module' flag is provided. +tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS2300: Duplicate identifier 'f'. +tests/cases/compiler/nonMergedOverloads.ts(4,17): error TS2300: Duplicate identifier 'f'. + + +==== tests/cases/compiler/nonMergedOverloads.ts (4 errors) ==== + var f = 10; + ~ +!!! error TS2300: Duplicate identifier 'f'. + + export function f(); + ~ +!!! error TS1148: Cannot compile modules unless the '--module' flag is provided. + ~ +!!! error TS2300: Duplicate identifier 'f'. + export function f() { + ~ +!!! error TS2300: Duplicate identifier 'f'. + } \ No newline at end of file diff --git a/tests/baselines/reference/nonMergedOverloads.js b/tests/baselines/reference/nonMergedOverloads.js new file mode 100644 index 00000000000..2e7f7f67ee6 --- /dev/null +++ b/tests/baselines/reference/nonMergedOverloads.js @@ -0,0 +1,12 @@ +//// [nonMergedOverloads.ts] +var f = 10; + +export function f(); +export function f() { +} + +//// [nonMergedOverloads.js] +var f = 10; +function f() { +} +exports.f = f; diff --git a/tests/cases/compiler/nonMergedOverloads.ts b/tests/cases/compiler/nonMergedOverloads.ts new file mode 100644 index 00000000000..582cd72e1f4 --- /dev/null +++ b/tests/cases/compiler/nonMergedOverloads.ts @@ -0,0 +1,5 @@ +var f = 10; + +export function f(); +export function f() { +} \ No newline at end of file From 762e1eb0a886a13de3b62b771c1778ae506ccbd0 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 14 Nov 2015 13:57:11 -0800 Subject: [PATCH 77/93] cleanup harness code --- src/harness/compilerRunner.ts | 13 +- src/harness/fourslash.ts | 36 ++- src/harness/harness.ts | 330 ++++++++++---------------- src/harness/harnessLanguageService.ts | 10 +- src/harness/rwcRunner.ts | 4 +- src/harness/test262Runner.ts | 11 +- 6 files changed, 161 insertions(+), 243 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index fd8b248dfe2..85a51b8f2a4 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -55,7 +55,6 @@ class CompilerBaselineRunner extends RunnerBase { let rootDir: string; let result: Harness.Compiler.CompilerResult; - let program: ts.Program; let options: ts.CompilerOptions; // equivalent to the files that will be passed on the command line let toBeCompiled: Harness.Compiler.TestFile[]; @@ -89,12 +88,11 @@ class CompilerBaselineRunner extends RunnerBase { }); } - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined); options = output.options; result = output.result; - program = output.program; }); after(() => { @@ -108,7 +106,6 @@ class CompilerBaselineRunner extends RunnerBase { lastUnit = undefined; rootDir = undefined; result = undefined; - program = undefined; options = undefined; toBeCompiled = undefined; otherFiles = undefined; @@ -181,7 +178,7 @@ class CompilerBaselineRunner extends RunnerBase { } const declFileCompilationResult = - Harness.Compiler.HarnessCompiler.compileDeclarationFiles( + Harness.Compiler.compileDeclarationFiles( toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined); if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) { @@ -253,10 +250,10 @@ class CompilerBaselineRunner extends RunnerBase { // These types are equivalent, but depend on what order the compiler observed // certain parts of the program. - const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); + const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)); - const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); - const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ false); + const fullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ true); + const pullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ false); const fullResults: ts.Map = {}; const pullResults: ts.Map = {}; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ebc58096d6f..f62e1c58412 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2383,10 +2383,9 @@ namespace FourSlash { // here we cache the JS output and reuse it for every test. let fourslashJsOutput: string; { - const fourslashFile: Harness.Compiler.TestFileWithPath = { + const fourslashFile: Harness.Compiler.TestFile = { unitName: Harness.Compiler.fourslashFileName, - content: undefined, - path: ts.toPath(Harness.Compiler.fourslashFileName, Harness.IO.getCurrentDirectory(), Harness.Compiler.getCanonicalFileName) + content: undefined }; const host = Harness.Compiler.createCompilerHost([fourslashFile], (fn, contents) => fourslashJsOutput = contents, @@ -2399,35 +2398,28 @@ namespace FourSlash { program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); } - export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); 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 = { + const fourslashFile: Harness.Compiler.TestFile = { unitName: Harness.Compiler.fourslashFileName, content: undefined, - path: ts.toPath(Harness.Compiler.fourslashFileName, currentDirectory, getCanonicalFileName) }; - const testFile: Harness.Compiler.TestFileWithPath = { + const testFile: Harness.Compiler.TestFile = { unitName: fileName, - content: content, - path: ts.toPath(fileName, currentDirectory, getCanonicalFileName) + content: content }; const host = Harness.Compiler.createCompilerHost( [ fourslashFile, testFile ], (fn, contents) => result = contents, ts.ScriptTarget.Latest, - useCaseSensitiveFileNames, - currentDirectory); + Harness.IO.useCaseSensitiveFileNames(), + Harness.IO.getCurrentDirectory()); const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host); @@ -2444,18 +2436,22 @@ namespace FourSlash { result = fourslashJsOutput + "\r\n" + result; + runCode(result); + + const xmlData = currentTestState.getTestXmlData(); + xmlData.originalName = fileName; + return xmlData; + } + + function runCode(code: string): void { // Compile and execute the test try { - eval(result); + eval(code); } catch (err) { // Debugging: FourSlash.currentTestState.printCurrentFileState(); throw err; } - - const xmlData = currentTestState.getTestXmlData(); - xmlData.originalName = fileName; - return xmlData; } function chompLeadingSpace(content: string) { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 9bc36e257ad..e58e6635434 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -767,25 +767,8 @@ namespace Harness { } namespace Harness { - let tcServicesFileName = "typescriptServices.js"; - - export let libFolder: string; - switch (Utils.getExecutionEnvironment()) { - case Utils.ExecutionEnvironment.CScript: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - case Utils.ExecutionEnvironment.Node: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - case Utils.ExecutionEnvironment.Browser: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - default: - throw new Error("Unknown context"); - } + const tcServicesFileName = "built/local/typescriptServices.js"; + export const libFolder = "built/local/"; export let tcServicesFile = IO.readFile(tcServicesFileName); export interface SourceMapEmitterCallback { @@ -827,57 +810,14 @@ namespace Harness { } } - export interface IEmitterIOHost { - writeFile(path: string, contents: string, writeByteOrderMark: boolean): void; - resolvePath(path: string): string; - } - - /** Mimics having multiple files, later concatenated to a single file. */ - export class EmitterIOHost implements IEmitterIOHost { - private fileCollection: any = {}; - - /** create file gets the whole path to create, so this works as expected with the --out parameter */ - public writeFile(s: string, contents: string, writeByteOrderMark: boolean): void { - let writer: ITextWriter; - if (this.fileCollection[s]) { - writer = this.fileCollection[s]; - } - else { - writer = new Harness.Compiler.WriterAggregator(); - this.fileCollection[s] = writer; - } - - writer.Write(contents); - writer.Close(); - } - - public resolvePath(s: string) { return s; } - - public reset() { this.fileCollection = {}; } - - public toArray(): { fileName: string; file: WriterAggregator; }[] { - const result: { fileName: string; file: WriterAggregator; }[] = []; - for (const p in this.fileCollection) { - if (this.fileCollection.hasOwnProperty(p)) { - const current = this.fileCollection[p]; - if (current.lines.length > 0) { - if (p.indexOf(".d.ts") !== -1) { current.lines.unshift(["////[", Path.getFileName(p), "]"].join("")); } - result.push({ fileName: p, file: this.fileCollection[p] }); - } - } - } - return result; - } - } - export function createSourceFileAndAssertInvariants( fileName: string, sourceText: string, languageVersion: ts.ScriptTarget) { - // We'll only assert inletiants outside of light mode. + // We'll only assert invariants outside of light mode. const shouldAssertInvariants = !Harness.lightMode; - // Only set the parent nodes if we're asserting inletiants. We don't need them otherwise. + // Only set the parent nodes if we're asserting invariants. We don't need them otherwise. const result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); if (shouldAssertInvariants) { @@ -890,12 +830,12 @@ namespace Harness { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; - export let defaultLibFileName = "lib.d.ts"; - export let defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); - export let defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); + export const defaultLibFileName = "lib.d.ts"; + export const defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); + export const defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); // Cache these between executions so we don't have to re-parse them for every test - export let fourslashFileName = "fourslash.ts"; + export const fourslashFileName = "fourslash.ts"; export let fourslashSourceFile: ts.SourceFile; export function getCanonicalFileName(fileName: string): string { @@ -903,7 +843,7 @@ namespace Harness { } export function createCompilerHost( - inputFiles: TestFileWithPath[], + inputFiles: TestFile[], writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void, scriptTarget: ts.ScriptTarget, useCaseSensitiveFileNames: boolean, @@ -915,16 +855,14 @@ namespace Harness { const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); const fileMap: ts.FileMap = ts.createFileMap(); - - // Register input files - function register(file: TestFileWithPath) { + for (const file of inputFiles) { if (file.content !== undefined) { const fileName = ts.normalizePath(file.unitName); const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget); - fileMap.set(file.path, sourceFile); + const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName); + fileMap.set(path, sourceFile); } - }; - inputFiles.forEach(register); + } function getSourceFile(fn: string, languageVersion: ts.ScriptTarget) { fn = ts.normalizePath(fn); @@ -1031,147 +969,133 @@ namespace Harness { unitName: string; content: string; } - export interface TestFileWithPath extends TestFile { - path: ts.Path; - } export interface CompilationOutput { result: CompilerResult; - program: ts.Program; 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): CompilationOutput { + 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): CompilationOutput { - 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; + 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; - const newLine = "\r\n"; - currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); + const newLine = "\r\n"; + currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); - // Parse settings - let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); - if (harnessSettings) { - setCompilerOptionsFromHarnessSetting(harnessSettings, options); - } - if (options.useCaseSensitiveFileNames !== undefined) { - useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; - } - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - const inputFilesWithPath = 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: TestFileWithPath[] = []; - if (options.includeBuiltFile) { - const builtFileName = libFolder + options.includeBuiltFile; - const builtFile: TestFileWithPath = { - unitName: builtFileName, - content: normalizeLineEndings(IO.readFile(builtFileName), newLine), - path: ts.toPath(builtFileName, currentDirectory, getCanonicalFileName) - }; - includeBuiltFiles.push(builtFile); - } - - const fileOutputs: GeneratedFile[] = []; - - const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); - - const compilerHost = createCompilerHost( - 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); - - const emitResult = program.emit(); - - const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); - - const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); - return { result, program, options }; + // Parse settings + let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); + if (harnessSettings) { + setCompilerOptionsFromHarnessSetting(harnessSettings, options); + } + if (options.useCaseSensitiveFileNames !== undefined) { + useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; } - export function compileDeclarationFiles(inputFiles: TestFile[], - otherFiles: TestFile[], - result: CompilerResult, - 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) { - 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"); + // 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: TestFile[] = []; + if (options.includeBuiltFile) { + const builtFileName = libFolder + options.includeBuiltFile; + const builtFile: TestFile = { + unitName: builtFileName, + content: normalizeLineEndings(IO.readFile(builtFileName), newLine), + }; + includeBuiltFiles.push(builtFile); + } + + const fileOutputs: GeneratedFile[] = []; + + const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); + + const compilerHost = createCompilerHost( + inputFiles.concat(includeBuiltFiles).concat(otherFiles), + (fileName, code, writeByteOrderMark) => fileOutputs.push({ fileName, code, writeByteOrderMark }), + options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); + const program = ts.createProgram(programFiles, options, compilerHost); + + const emitResult = program.emit(); + + const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); + return { result, options }; + } + + export function compileDeclarationFiles(inputFiles: TestFile[], + otherFiles: TestFile[], + result: CompilerResult, + 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) { + 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: 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)); + const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory); + + return { declInputFiles, declOtherFiles, declResult: output.result }; + } + + function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { + if (isDTS(file.unitName)) { + dtsFiles.push(file); } - - 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)); - const output = this.compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory); - - return { declInputFiles, declOtherFiles, declResult: output.result }; - } - - function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { - if (isDTS(file.unitName)) { - dtsFiles.push(file); - } - else if (isTS(file.unitName)) { - const declFile = findResultCodeFile(file.unitName); - if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { - dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); - } - } - - function findResultCodeFile(fileName: string) { - const sourceFile = result.program.getSourceFile(fileName); - assert(sourceFile, "Program has no source file with name '" + fileName + "'"); - // Is this file going to be emitted separately - let sourceFileName: string; - const outFile = options.outFile || options.out; - if (ts.isExternalModule(sourceFile) || !outFile) { - if (options.outDir) { - let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); - sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); - sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); - } - else { - sourceFileName = sourceFile.fileName; - } - } - else { - // Goes to single --out file - sourceFileName = outFile; - } - - const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; - - return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); - } - - function findUnit(fileName: string, units: TestFile[]) { - return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined); + else if (isTS(file.unitName)) { + const declFile = findResultCodeFile(file.unitName); + if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { + dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); } } } + + function findResultCodeFile(fileName: string) { + const sourceFile = result.program.getSourceFile(fileName); + assert(sourceFile, "Program has no source file with name '" + fileName + "'"); + // Is this file going to be emitted separately + let sourceFileName: string; + const outFile = options.outFile || options.out; + if (ts.isExternalModule(sourceFile) || !outFile) { + if (options.outDir) { + let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); + sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); + sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); + } + else { + sourceFileName = sourceFile.fileName; + } + } + else { + // Goes to single --out file + sourceFileName = outFile; + } + + const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; + + return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); + } + + function findUnit(fileName: string, units: TestFile[]) { + return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined); + } } function normalizeLineEndings(text: string, lineEnding: string): string { @@ -1388,7 +1312,7 @@ namespace Harness { constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program, public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) { - fileResults.forEach(emittedFile => { + for (const emittedFile of fileResults) { if (isDTS(emittedFile.fileName)) { // .d.ts file, add to declFiles emit this.declFilesCode.push(emittedFile); @@ -1403,7 +1327,7 @@ namespace Harness { else { throw new Error("Unrecognized file extension for file " + emittedFile.fileName); } - }); + } this.errors = errors; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 0c267c38f14..3c7814df562 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -7,7 +7,7 @@ namespace Harness.LanguageService { export class ScriptInfo { public version: number = 1; public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = []; - public lineMap: number[] = undefined; + private lineMap: number[] = undefined; constructor(public fileName: string, public content: string) { this.setContent(content); @@ -15,7 +15,11 @@ namespace Harness.LanguageService { private setContent(content: string): void { this.content = content; - this.lineMap = ts.computeLineStarts(content); + this.lineMap = undefined; + } + + public getLineMap(): number[] { + return this.lineMap || (this.lineMap = ts.computeLineStarts(this.content)); } public updateContent(content: string): void { @@ -164,7 +168,7 @@ namespace Harness.LanguageService { const script: ScriptInfo = this.fileNameToScript[fileName]; assert.isNotNull(script); - return ts.computeLineAndCharacterOfPosition(script.lineMap, position); + return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position); } } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index fc1397b294c..ce570a7d6ad 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -126,7 +126,7 @@ namespace RWC { // Emit the results compilerOptions = null; - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( inputFiles, otherFiles, /* harnessOptions */ undefined, @@ -202,7 +202,7 @@ 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.HarnessCompiler.compileDeclarationFiles( + const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles( inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory); if (declFileCompilationResult.declResult.errors.length === 0) { diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 859f10dc4cc..262145b4764 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -32,7 +32,6 @@ class Test262BaselineRunner extends RunnerBase { filename: string; compilerResult: Harness.Compiler.CompilerResult; inputFiles: Harness.Compiler.TestFile[]; - program: ts.Program; }; before(() => { @@ -50,10 +49,9 @@ class Test262BaselineRunner extends RunnerBase { filename: testFilename, inputFiles: inputFiles, compilerResult: undefined, - program: undefined, }; - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( [Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], /* harnessOptions */ undefined, @@ -61,7 +59,6 @@ class Test262BaselineRunner extends RunnerBase { /* currentDirectory */ undefined ); testState.compilerResult = output.result; - testState.program = output.program; }); after(() => { @@ -86,14 +83,14 @@ class Test262BaselineRunner extends RunnerBase { }, false, Test262BaselineRunner.baselineOptions); }); - it("satisfies inletiants", () => { - const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + it("satisfies invariants", () => { + const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it("has the expected AST", () => { Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => { - const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); return Utils.sourceFileToJSON(sourceFile); }, false, Test262BaselineRunner.baselineOptions); }); From eda75fbfd528875bb23d3eb07cb3afb689d51829 Mon Sep 17 00:00:00 2001 From: tobisek Date: Sun, 15 Nov 2015 15:03:43 +0200 Subject: [PATCH 78/93] added default chrome path for Mac OS X --- tests/webTestServer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts index 6bd15359e3f..dab552e2619 100644 --- a/tests/webTestServer.ts +++ b/tests/webTestServer.ts @@ -269,6 +269,9 @@ if ((browser && browser === 'chrome')) { case "win64": defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"; break; + case "darwin": + defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; + break; case "linux": defaultChromePath = "/opt/google/chrome/chrome" break; From 078ed3f4856c527cd4cfcfc23166d1f74c041ea8 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 09:49:58 -0800 Subject: [PATCH 79/93] use normalized absolute file names when doing consistency check --- src/compiler/program.ts | 16 +++++++-------- tests/cases/unittests/moduleResolution.ts | 25 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 86fbc2e6259..57207d0564a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -800,12 +800,12 @@ namespace ts { } // Get source file from normalized fileName - function findSourceFile(fileName: string, normalizedAbsolutePath: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile { - if (filesByName.contains(normalizedAbsolutePath)) { - const file = filesByName.get(normalizedAbsolutePath); + function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile { + if (filesByName.contains(path)) { + const file = filesByName.get(path); // try to check if we've already seen this file but with a different casing in path // NOTE: this only makes sense for case-insensitive file systems - if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== normalizedAbsolutePath) { + if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== getNormalizedAbsolutePath(fileName, currentDirectory)) { reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd); } @@ -823,18 +823,18 @@ namespace ts { } }); - filesByName.set(normalizedAbsolutePath, file); + filesByName.set(path, file); if (file) { - file.path = normalizedAbsolutePath; + file.path = path; if (host.useCaseSensitiveFileNames()) { // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case - const existingFile = filesByNameIgnoreCase.get(normalizedAbsolutePath); + const existingFile = filesByNameIgnoreCase.get(path); if (existingFile) { reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); } else { - filesByNameIgnoreCase.set(normalizedAbsolutePath, file); + filesByNameIgnoreCase.set(path, file); } } diff --git a/tests/cases/unittests/moduleResolution.ts b/tests/cases/unittests/moduleResolution.ts index c53cad5725a..9e316266bf6 100644 --- a/tests/cases/unittests/moduleResolution.ts +++ b/tests/cases/unittests/moduleResolution.ts @@ -354,6 +354,31 @@ export = C; "moduleC.ts": "export var x" }; test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /* useCaseSensitiveFileNames */ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]); + }); + + it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => { + const files: Map = { + "/a/B/c/moduleA.ts": `import a = require("./ModuleC")`, + "/a/B/c/moduleB.ts": `import a = require("./moduleC")`, + "/a/B/c/moduleC.ts": "export var x", + "/a/B/c/moduleD.ts": ` +import a = require("./moduleA.ts"); +import b = require("./moduleB.ts"); + ` + }; + test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], [1149]); + }); + it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => { + const files: Map = { + "/a/B/c/moduleA.ts": `import a = require("./moduleC")`, + "/a/B/c/moduleB.ts": `import a = require("./moduleC")`, + "/a/B/c/moduleC.ts": "export var x", + "/a/B/c/moduleD.ts": ` +import a = require("./moduleA.ts"); +import b = require("./moduleB.ts"); + ` + }; + test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], []); }) }); } \ No newline at end of file From 8039909913be85531b09cef6cc31a61542cc5408 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 10:36:13 -0800 Subject: [PATCH 80/93] remove Tao generation --- src/harness/fourslash.ts | 282 +++++---------------------------- src/harness/fourslashRunner.ts | 50 ------ 2 files changed, 37 insertions(+), 295 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index f62e1c58412..88458beaba4 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -48,12 +48,6 @@ namespace FourSlash { ranges: Range[]; } - export interface TestXmlData { - invalidReason: string; - originalName: string; - actions: string[]; - } - interface MemberListData { result: { maybeInaccurate: boolean; @@ -84,14 +78,14 @@ namespace FourSlash { marker?: Marker; } - interface ILocationInformation { + interface LocationInformation { position: number; sourcePosition: number; sourceLine: number; sourceColumn: number; } - interface IRangeLocationInformation extends ILocationInformation { + interface RangeLocationInformation extends LocationInformation { marker?: Marker; } @@ -134,11 +128,6 @@ namespace FourSlash { return settings; } - export let currentTestState: TestState = null; - function assertionMessage(msg: string) { - return "\nMarker: " + currentTestState.lastKnownMarker + "\nChecking: " + msg + "\n\n"; - } - export class TestCancellationToken implements ts.HostCancellationToken { // 0 - cancelled // >0 - not cancelled @@ -216,9 +205,6 @@ namespace FourSlash { public formatCodeOptions: ts.FormatCodeOptions; - private scenarioActions: string[] = []; - private taoInvalidReason: string = null; - private inputFiles: ts.Map = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references // Add input file which has matched file name with the given reference-file path. @@ -338,7 +324,6 @@ namespace FourSlash { this.testData.files.forEach(file => { const fileName = file.fileName.replace(Harness.IO.directoryName(file.fileName), "").substr(1); const fileNameWithoutExtension = fileName.substr(0, fileName.lastIndexOf(".")); - this.scenarioActions.push(""); }); // Open the first file by default @@ -367,21 +352,11 @@ namespace FourSlash { public goToPosition(pos: number) { this.currentCaretPosition = pos; - - const lineStarts = ts.computeLineStarts(this.getFileContent(this.activeFile.fileName)); - const lineCharPos = ts.computeLineAndCharacterOfPosition(lineStarts, pos); - this.scenarioActions.push(``); } public moveCaretRight(count = 1) { this.currentCaretPosition += count; this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length); - if (count > 0) { - this.scenarioActions.push(``); - } - else { - this.scenarioActions.push(``); - } } // Opens a file given its 0-based index or fileName @@ -391,9 +366,6 @@ namespace FourSlash { const fileToOpen: FourSlashFile = this.findFile(indexOrName); fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName); this.activeFile = fileToOpen; - const fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), "").substr(1); - this.scenarioActions.push(``); - // Let the host know that this file is now open this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content); } @@ -407,8 +379,6 @@ namespace FourSlash { const exists = this.anyErrorInRange(predicate, startMarker, endMarker); - this.taoInvalidReason = "verifyErrorExistsBetweenMarkers NYI"; - if (exists !== negative) { this.printErrorLog(negative, this.getAllDiagnostics()); throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName); @@ -421,7 +391,11 @@ namespace FourSlash { } private messageAtLastKnownMarker(message: string) { - return "Marker: " + currentTestState.lastKnownMarker + "\n" + message; + return "Marker: " + this.lastKnownMarker + "\n" + message; + } + + private assertionMessageAtLastKnownMarker(msg: string) { + return "\nMarker: " + this.lastKnownMarker + "\nChecking: " + msg + "\n\n"; } private getDiagnostics(fileName: string): ts.Diagnostic[] { @@ -461,8 +435,6 @@ namespace FourSlash { }; } - this.taoInvalidReason = "verifyErrorExistsAfterMarker NYI"; - const exists = this.anyErrorInRange(predicate, marker); const diagnostics = this.getAllDiagnostics(); @@ -511,8 +483,6 @@ namespace FourSlash { const errors = this.getDiagnostics(this.activeFile.fileName); const actual = errors.length; - this.scenarioActions.push(``); - if (actual !== expected) { this.printErrorLog(/*expectErrors*/ false, errors); const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; @@ -527,8 +497,6 @@ namespace FourSlash { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } - this.taoInvalidReason = "verifyEval impossible"; - const evaluation = new Function(`${emit.outputFiles[0].text};\r\nreturn (${expr});`)(); if (evaluation !== value) { this.raiseError(`Expected evaluation of expression "${expr}" to equal "${value}", but got "${evaluation}"`); @@ -540,7 +508,6 @@ namespace FourSlash { if (emit.outputFiles.length !== 1) { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } - this.taoInvalidReason = "verifyGetEmitOutputForCurrentFile impossible"; const actual = emit.outputFiles[0].text; if (actual !== expected) { this.raiseError(`Expected emit output to be "${expected}", but got "${actual}"`); @@ -548,13 +515,6 @@ namespace FourSlash { } public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - - if (text || documentation || kind) { - this.taoInvalidReason = "verifyMemberListContains only supports the \"symbol\" parameter"; - } - const members = this.getMemberListAtCaret(); if (members) { this.assertItemInCompletionList(members.entries, symbol, text, documentation, kind); @@ -565,18 +525,9 @@ namespace FourSlash { } public verifyMemberListCount(expectedCount: number, negative: boolean) { - if (expectedCount === 0) { - if (negative) { - this.verifyMemberListIsEmpty(/*negative*/ false); - return; - } - else { - this.scenarioActions.push(""); - } - } - else { - this.scenarioActions.push(""); - this.scenarioActions.push(``); + if (expectedCount === 0 && negative) { + this.verifyMemberListIsEmpty(/*negative*/ false); + return; } const members = this.getMemberListAtCaret(); @@ -594,9 +545,6 @@ namespace FourSlash { } public verifyMemberListDoesNotContain(symbol: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - const members = this.getMemberListAtCaret(); if (members && members.entries.filter(e => e.name === symbol).length !== 0) { this.raiseError(`Member list did contain ${symbol}`); @@ -604,8 +552,6 @@ namespace FourSlash { } public verifyCompletionListItemsCountIsGreaterThan(count: number, negative: boolean) { - this.taoInvalidReason = "verifyCompletionListItemsCountIsGreaterThan NYI"; - const completions = this.getCompletionListAtCaret(); const itemsCount = completions.entries.length; @@ -622,13 +568,6 @@ namespace FourSlash { } public verifyMemberListIsEmpty(negative: boolean) { - if (negative) { - this.scenarioActions.push(""); - } - else { - this.scenarioActions.push(""); - } - const members = this.getMemberListAtCaret(); if ((!members || members.entries.length === 0) && negative) { this.raiseError("Member list is empty at Caret"); @@ -647,8 +586,6 @@ namespace FourSlash { } public verifyCompletionListIsEmpty(negative: boolean) { - this.scenarioActions.push(""); - const completions = this.getCompletionListAtCaret(); if ((!completions || completions.entries.length === 0) && negative) { this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition); @@ -716,8 +653,6 @@ namespace FourSlash { // and keep it in the list of filtered entry. return true; } - this.scenarioActions.push(""); - this.scenarioActions.push(``); const completions = this.getCompletionListAtCaret(); if (completions) { @@ -745,24 +680,20 @@ namespace FourSlash { } public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) { - this.taoInvalidReason = "verifyCompletionEntryDetails NYI"; - const details = this.getCompletionEntryDetails(entryName); - assert.equal(ts.displayPartsToString(details.displayParts), expectedText, assertionMessage("completion entry details text")); + assert.equal(ts.displayPartsToString(details.displayParts), expectedText, this.assertionMessageAtLastKnownMarker("completion entry details text")); if (expectedDocumentation !== undefined) { - assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, assertionMessage("completion entry documentation")); + assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, this.assertionMessageAtLastKnownMarker("completion entry documentation")); } if (kind !== undefined) { - assert.equal(details.kind, kind, assertionMessage("completion entry kind")); + assert.equal(details.kind, kind, this.assertionMessageAtLastKnownMarker("completion entry kind")); } } public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { - this.taoInvalidReason = "verifyReferencesAtPositionListContains NYI"; - const references = this.getReferencesAtCaret(); if (!references || references.length === 0) { @@ -784,8 +715,6 @@ namespace FourSlash { } public verifyReferencesCountIs(count: number, localFilesOnly = true) { - this.taoInvalidReason = "verifyReferences NYI"; - const references = this.getReferencesAtCaret(); let referencesCount = 0; @@ -845,13 +774,6 @@ namespace FourSlash { } public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) { - [expectedText, expectedDocumentation].forEach(str => { - if (str) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - } - }); - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; @@ -871,7 +793,7 @@ namespace FourSlash { } // TODO: should be '==='? if (expectedDocumentation != undefined) { - assert.equal(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc")); + assert.equal(actualQuickInfoDocumentation, expectedDocumentation, this.assertionMessageAtLastKnownMarker("quick info doc")); } } } @@ -879,8 +801,6 @@ namespace FourSlash { public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { let result = ""; @@ -947,8 +867,6 @@ namespace FourSlash { } public verifyQuickInfoExists(negative: boolean) { - this.taoInvalidReason = "verifyQuickInfoExists NYI"; - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (negative) { if (actualQuickInfo) { @@ -963,8 +881,6 @@ namespace FourSlash { } public verifyCurrentSignatureHelpIs(expected: string) { - this.taoInvalidReason = "verifyCurrentSignatureHelpIs NYI"; - const help = this.getActiveSignatureHelpItem(); assert.equal( ts.displayPartsToString(help.prefixDisplayParts) + @@ -973,75 +889,51 @@ namespace FourSlash { } public verifyCurrentParameterIsletiable(isVariable: boolean) { - this.taoInvalidReason = "verifyCurrentParameterIsletiable NYI"; - const signature = this.getActiveSignatureHelpItem(); assert.isNotNull(signature); assert.equal(isVariable, signature.isVariadic); } public verifyCurrentParameterHelpName(name: string) { - this.taoInvalidReason = "verifyCurrentParameterHelpName NYI"; - const activeParameter = this.getActiveParameter(); const activeParameterName = activeParameter.name; assert.equal(activeParameterName, name); } public verifyCurrentParameterSpanIs(parameter: string) { - this.taoInvalidReason = "verifyCurrentParameterSpanIs NYI"; - const activeSignature = this.getActiveSignatureHelpItem(); const activeParameter = this.getActiveParameter(); assert.equal(ts.displayPartsToString(activeParameter.displayParts), parameter); } public verifyCurrentParameterHelpDocComment(docComment: string) { - this.taoInvalidReason = "verifyCurrentParameterHelpDocComment NYI"; - const activeParameter = this.getActiveParameter(); const activeParameterDocComment = activeParameter.documentation; - assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, assertionMessage("current parameter Help DocComment")); + assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, this.assertionMessageAtLastKnownMarker("current parameter Help DocComment")); } public verifyCurrentSignatureHelpParameterCount(expectedCount: number) { - this.taoInvalidReason = "verifyCurrentSignatureHelpParameterCount NYI"; - assert.equal(this.getActiveSignatureHelpItem().parameters.length, expectedCount); } - public verifyCurrentSignatureHelpTypeParameterCount(expectedCount: number) { - this.taoInvalidReason = "verifyCurrentSignatureHelpTypeParameterCount NYI"; - - // assert.equal(this.getActiveSignatureHelpItem().typeParameters.length, expectedCount); - } - public verifyCurrentSignatureHelpDocComment(docComment: string) { - this.taoInvalidReason = "verifyCurrentSignatureHelpDocComment NYI"; - const actualDocComment = this.getActiveSignatureHelpItem().documentation; - assert.equal(ts.displayPartsToString(actualDocComment), docComment, assertionMessage("current signature help doc comment")); + assert.equal(ts.displayPartsToString(actualDocComment), docComment, this.assertionMessageAtLastKnownMarker("current signature help doc comment")); } public verifySignatureHelpCount(expected: number) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); const actual = help && help.items ? help.items.length : 0; assert.equal(actual, expected); } public verifySignatureHelpArgumentCount(expected: number) { - this.taoInvalidReason = "verifySignatureHelpArgumentCount NYI"; const signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); const actual = signatureHelpItems.argumentCount; assert.equal(actual, expected); } public verifySignatureHelpPresent(shouldBePresent = true) { - this.taoInvalidReason = "verifySignatureHelpPresent NYI"; - const actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); if (shouldBePresent) { if (!actual) { @@ -1184,13 +1076,10 @@ namespace FourSlash { } public getBreakpointStatementLocation(pos: number) { - this.taoInvalidReason = "getBreakpointStatementLocation NYI"; return this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos); } public baselineCurrentFileBreakpointLocations() { - this.taoInvalidReason = "baselineCurrentFileBreakpointLocations impossible"; - Harness.Baseline.runBaseline( "Breakpoint Locations for " + this.activeFile.fileName, this.testData.globalOptions[metadataOptionNames.baselineFile], @@ -1201,7 +1090,6 @@ namespace FourSlash { } public baselineGetEmitOutput() { - this.taoInvalidReason = "baselineGetEmitOutput impossible"; // Find file to be emitted const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on @@ -1327,8 +1215,6 @@ namespace FourSlash { } public deleteChar(count = 1) { - this.scenarioActions.push(``); - let offset = this.currentCaretPosition; const ch = ""; @@ -1340,7 +1226,7 @@ namespace FourSlash { this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Handle post-keystroke formatting @@ -1357,20 +1243,16 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } public replace(start: number, length: number, text: string) { - this.taoInvalidReason = "replace NYI"; - this.languageServiceAdapterHost.editScript(this.activeFile.fileName, start, start + length, text); this.updateMarkersForEdit(this.activeFile.fileName, start, start + length, text); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } public deleteCharBehindMarker(count = 1) { - this.scenarioActions.push(``); - let offset = this.currentCaretPosition; const ch = ""; const checkCadence = (count >> 2) + 1; @@ -1382,7 +1264,7 @@ namespace FourSlash { this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Handle post-keystroke formatting @@ -1398,18 +1280,11 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Enters lines of text at the current caret position public type(text: string) { - if (text === "") { - this.taoInvalidReason = "Test used empty-insert workaround."; - } - else { - this.scenarioActions.push(``); - } - return this.typeHighFidelity(text); } @@ -1440,7 +1315,7 @@ namespace FourSlash { } if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); // this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); // this.languageService.getSemanticDiagnostics(this.activeFile.fileName); } @@ -1459,18 +1334,16 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Enters text as if the user had pasted it public paste(text: string) { - this.scenarioActions.push(``); - const start = this.currentCaretPosition; let offset = this.currentCaretPosition; this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, text); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, text); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); offset += text.length; // Handle formatting @@ -1478,7 +1351,7 @@ namespace FourSlash { const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } } @@ -1486,10 +1359,10 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } - private checkPostEditInletiants() { + private checkPostEditInvariants() { if (this.testType !== FourSlashTestType.Native) { // getSourcefile() results can not be serialized. Only perform these verifications // if running against a native LS object. @@ -1560,16 +1433,12 @@ namespace FourSlash { } public formatDocument() { - this.scenarioActions.push(""); - const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); } public formatSelection(start: number, end: number) { - this.taoInvalidReason = "formatSelection NYI"; - const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); @@ -1603,13 +1472,6 @@ namespace FourSlash { } public goToDefinition(definitionIndex: number) { - if (definitionIndex === 0) { - this.scenarioActions.push(""); - } - else { - this.taoInvalidReason = "GoToDefinition not supported for non-zero definition indices"; - } - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError("goToDefinition failed - expected to at least one definition location but got 0"); @@ -1625,13 +1487,6 @@ namespace FourSlash { } public goToTypeDefinition(definitionIndex: number) { - if (definitionIndex === 0) { - this.scenarioActions.push(""); - } - else { - this.taoInvalidReason = "GoToTypeDefinition not supported for non-zero definition indices"; - } - const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0"); @@ -1647,8 +1502,6 @@ namespace FourSlash { } public verifyDefinitionLocationExists(negative: boolean) { - this.taoInvalidReason = "verifyDefinitionLocationExists NYI"; - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); const foundDefinitions = definitions && definitions.length; @@ -1680,8 +1533,6 @@ namespace FourSlash { } public verifyDefinitionsName(negative: boolean, expectedName: string, expectedContainerName: string) { - this.taoInvalidReason = "verifyDefinititionsInfo NYI"; - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); const actualDefinitionName = definitions && definitions.length ? definitions[0].name : ""; const actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : ""; @@ -1706,8 +1557,6 @@ namespace FourSlash { } public verifyCaretAtMarker(markerName = "") { - this.taoInvalidReason = "verifyCaretAtMarker NYI"; - const pos = this.getMarkerByName(markerName); if (pos.fileName !== this.activeFile.fileName) { throw new Error(`verifyCaretAtMarker failed - expected to be in file "${pos.fileName}", but was in file "${this.activeFile.fileName}"`); @@ -1726,8 +1575,6 @@ namespace FourSlash { } public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) { - this.taoInvalidReason = "verifyIndentationAtCurrentPosition NYI"; - const actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle); const lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); if (actual !== numberOfSpaces) { @@ -1736,8 +1583,6 @@ namespace FourSlash { } public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) { - this.taoInvalidReason = "verifyIndentationAtPosition NYI"; - const actual = this.getIndentation(fileName, position, indentStyle); const lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { @@ -1746,8 +1591,6 @@ namespace FourSlash { } public verifyCurrentLineContent(text: string) { - this.taoInvalidReason = "verifyCurrentLineContent NYI"; - const actual = this.getCurrentLineContent(); if (actual !== text) { throw new Error("verifyCurrentLineContent\n" + @@ -1757,8 +1600,6 @@ namespace FourSlash { } public verifyCurrentFileContent(text: string) { - this.taoInvalidReason = "verifyCurrentFileContent NYI"; - const actual = this.getFileContent(this.activeFile.fileName); const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n"); if (replaceNewlines(actual) !== replaceNewlines(text)) { @@ -1769,8 +1610,6 @@ namespace FourSlash { } public verifyTextAtCaretIs(text: string) { - this.taoInvalidReason = "verifyCurrentFileContent NYI"; - const actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length); if (actual !== text) { throw new Error("verifyTextAtCaretIs\n" + @@ -1780,8 +1619,6 @@ namespace FourSlash { } public verifyCurrentNameOrDottedNameSpanText(text: string) { - this.taoInvalidReason = "verifyCurrentNameOrDottedNameSpanText NYI"; - const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); if (!span) { this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + @@ -1798,13 +1635,10 @@ namespace FourSlash { } private getNameOrDottedNameSpan(pos: number) { - this.taoInvalidReason = "getNameOrDottedNameSpan NYI"; return this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos); } public baselineCurrentFileNameOrDottedNameSpans() { - this.taoInvalidReason = "baselineCurrentFileNameOrDottedNameSpans impossible"; - Harness.Baseline.runBaseline( "Name OrDottedNameSpans for " + this.activeFile.fileName, this.testData.globalOptions[metadataOptionNames.baselineFile], @@ -1898,8 +1732,6 @@ namespace FourSlash { } public verifyOutliningSpans(spans: TextSpan[]) { - this.taoInvalidReason = "verifyOutliningSpans NYI"; - const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { @@ -1968,8 +1800,6 @@ namespace FourSlash { } public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { - this.taoInvalidReason = "verifyMatchingBracePosition NYI"; - const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 2) { @@ -1993,8 +1823,6 @@ namespace FourSlash { } public verifyNoMatchingBracePosition(bracePosition: number) { - this.taoInvalidReason = "verifyNoMatchingBracePosition NYI"; - const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 0) { @@ -2007,8 +1835,6 @@ namespace FourSlash { Report an error if expected value and actual value do not match. */ public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string) { - this.taoInvalidReason = "verifyNavigationItemsCount NYI"; - const items = this.languageService.getNavigateToItems(searchValue); let actual = 0; let item: ts.NavigateToItem = null; @@ -2037,8 +1863,6 @@ namespace FourSlash { matchKind: string, fileName?: string, parentName?: string) { - this.taoInvalidReason = "verifyNavigationItemsListContains NYI"; - const items = this.languageService.getNavigateToItems(searchValue); if (!items || items.length === 0) { @@ -2063,8 +1887,6 @@ namespace FourSlash { } public verifyGetScriptLexicalStructureListCount(expected: number) { - this.taoInvalidReason = "verifyNavigationItemsListContains impossible"; - const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const actual = this.getNavigationBarItemsCount(items); @@ -2086,8 +1908,6 @@ namespace FourSlash { } public verifyGetScriptLexicalStructureListContains(name: string, kind: string) { - this.taoInvalidReason = "verifyGetScriptLexicalStructureListContains impossible"; - const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); if (!items || items.length === 0) { @@ -2148,8 +1968,6 @@ namespace FourSlash { } public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { - this.taoInvalidReason = "verifyOccurrencesAtPositionListContains NYI"; - const occurrences = this.getOccurrencesAtCurrentPosition(); if (!occurrences || occurrences.length === 0) { @@ -2170,8 +1988,6 @@ namespace FourSlash { } public verifyOccurrencesAtPositionListCount(expectedCount: number) { - this.taoInvalidReason = "verifyOccurrencesAtPositionListCount NYI"; - const occurrences = this.getOccurrencesAtCurrentPosition(); const actualCount = occurrences ? occurrences.length : 0; if (expectedCount !== actualCount) { @@ -2185,8 +2001,6 @@ namespace FourSlash { } public verifyDocumentHighlightsAtPositionListContains(fileName: string, start: number, end: number, fileNamesToSearch: string[], kind?: string) { - this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListContains NYI"; - const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch); if (!documentHighlights || documentHighlights.length === 0) { @@ -2213,8 +2027,6 @@ namespace FourSlash { } public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) { - this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListCount NYI"; - const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch); const actualCount = documentHighlights ? documentHighlights.reduce((currentCount, { highlightSpans }) => currentCount + highlightSpans.length, 0) @@ -2255,13 +2067,6 @@ namespace FourSlash { } private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - - if (text || documentation || kind) { - this.taoInvalidReason = "assertItemInCompletionList only supports the \"name\" parameter"; - } - for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.name === name) { @@ -2269,15 +2074,15 @@ namespace FourSlash { const details = this.getCompletionEntryDetails(item.name); if (documentation !== undefined) { - assert.equal(ts.displayPartsToString(details.documentation), documentation, assertionMessage("completion item documentation for " + name)); + assert.equal(ts.displayPartsToString(details.documentation), documentation, this.assertionMessageAtLastKnownMarker("completion item documentation for " + name)); } if (text !== undefined) { - assert.equal(ts.displayPartsToString(details.displayParts), text, assertionMessage("completion item detail text for " + name)); + assert.equal(ts.displayPartsToString(details.displayParts), text, this.assertionMessageAtLastKnownMarker("completion item detail text for " + name)); } } if (kind !== undefined) { - assert.equal(item.kind, kind, assertionMessage("completion item kind for " + name)); + assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + name)); } return; @@ -2352,14 +2157,6 @@ namespace FourSlash { return text.replace(/ /g, "\u00B7").replace(/\r/g, "\u00B6").replace(/\n/g, "\u2193\n").replace(/\t/g, "\u2192\ "); } - public getTestXmlData(): TestXmlData { - return { - actions: this.scenarioActions, - invalidReason: this.taoInvalidReason, - originalName: "" - }; - } - public setCancelled(numberOfCalls: number): void { this.cancellationToken.setCancelled(numberOfCalls); } @@ -2372,11 +2169,9 @@ namespace FourSlash { // TOOD: should these just use the Harness's stdout/stderr? const fsOutput = new Harness.Compiler.WriterAggregator(); const fsErrors = new Harness.Compiler.WriterAggregator(); - export let xmlData: TestXmlData[] = []; export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) { const content = Harness.IO.readFile(fileName); - const xml = runFourSlashTestContent(basePath, testType, content, fileName); - xmlData.push(xml); + runFourSlashTestContent(basePath, testType, content, fileName); } // We don't want to recompile 'fourslash.ts' for every test, so @@ -2398,7 +2193,8 @@ namespace FourSlash { program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); } - export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData { + export let currentTestState: TestState; + export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); @@ -2437,10 +2233,6 @@ namespace FourSlash { result = fourslashJsOutput + "\r\n" + result; runCode(result); - - const xmlData = currentTestState.getTestXmlData(); - xmlData.originalName = fileName; - return xmlData; } function runCode(code: string): void { @@ -2619,7 +2411,7 @@ namespace FourSlash { throw new Error(errorMessage); } - function recordObjectMarker(fileName: string, location: ILocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker { + function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker { let markerValue: any = undefined; try { // Attempt to parse the marker value as JSON @@ -2650,7 +2442,7 @@ namespace FourSlash { return marker; } - function recordMarker(fileName: string, location: ILocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { + function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { const marker: Marker = { fileName: fileName, position: location.position @@ -2679,10 +2471,10 @@ namespace FourSlash { let output = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - let openMarker: ILocationInformation = null; + let openMarker: LocationInformation = null; /// A stack of the open range markers that are still unclosed - const openRanges: IRangeLocationInformation[] = []; + const openRanges: RangeLocationInformation[] = []; /// A list of ranges we've collected so far */ let localRanges: Range[] = []; diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts index 7228f06c20f..84e352359c4 100644 --- a/src/harness/fourslashRunner.ts +++ b/src/harness/fourslashRunner.ts @@ -58,56 +58,6 @@ class FourSlashRunner extends RunnerBase { } }); }); - - describe("Generate Tao XML", () => { - const invalidReasons: any = {}; - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1; - } - }); - const invalidReport: { reason: string; count: number }[] = []; - for (const reason in invalidReasons) { - if (invalidReasons.hasOwnProperty(reason)) { - invalidReport.push({ reason: reason, count: invalidReasons[reason] }); - } - } - invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1); - - const lines: string[] = []; - lines.push(""); - lines.push(""); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - lines.push(""); - } - else { - lines.push(" "); - xml.actions.forEach(action => { - lines.push(" " + action); - }); - lines.push(" "); - } - }); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(""); - Harness.IO.writeFile("built/local/fourslash.xml", lines.join("\r\n")); - }); }); } } From 31bce223d98ed976542c4d2cd654618f10cdfb9c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 11:50:42 -0800 Subject: [PATCH 81/93] switch fourslash to use local test state --- src/harness/fourslash.ts | 669 ++++++++++++- ...foreSemanticDiagnosticsInArrowFunction1.ts | 12 +- tests/cases/fourslash/fourslash.ts | 902 +++++------------- tests/cases/fourslash/indentationBlock.ts | 2 +- tests/cases/fourslash/indentationNone.ts | 2 +- .../fourslash/recursiveClassReference.ts | 2 +- tests/cases/fourslash/renameModuleToVar.ts | 8 +- 7 files changed, 909 insertions(+), 688 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 88458beaba4..5f48a885395 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2174,31 +2174,11 @@ namespace FourSlash { runFourSlashTestContent(basePath, testType, content, fileName); } - // We don't want to recompile 'fourslash.ts' for every test, so - // here we cache the JS output and reuse it for every test. - let fourslashJsOutput: string; - { - const fourslashFile: Harness.Compiler.TestFile = { - unitName: Harness.Compiler.fourslashFileName, - content: undefined - }; - const host = Harness.Compiler.createCompilerHost([fourslashFile], - (fn, contents) => fourslashJsOutput = contents, - ts.ScriptTarget.Latest, - Harness.IO.useCaseSensitiveFileNames(), - Harness.IO.getCurrentDirectory()); - - const program = ts.createProgram([Harness.Compiler.fourslashFileName], { noResolve: true, target: ts.ScriptTarget.ES3 }, host); - - program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); - } - - export let currentTestState: TestState; export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); - currentTestState = new TestState(basePath, testType, testData); + const state = new TestState(basePath, testType, testData); let result = ""; const fourslashFile: Harness.Compiler.TestFile = { @@ -2228,17 +2208,27 @@ namespace FourSlash { } program.emit(sourceFile); - result = result || ""; // Might have an empty fourslash file - result = fourslashJsOutput + "\r\n" + result; - - runCode(result); + ts.Debug.assert(!!result); + runCode(result, state); } - function runCode(code: string): void { + function runCode(code: string, state: TestState): void { // Compile and execute the test + const wrappedCode = +`(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) { +${code} +})`; try { - eval(code); + const test = new FourSlashInterface.Test(state); + const goTo = new FourSlashInterface.GoTo(state); + const verify = new FourSlashInterface.Verify(state); + const edit = new FourSlashInterface.Edit(state); + const debug = new FourSlashInterface.Debug(state); + const format = new FourSlashInterface.Format(state); + const cancellation = new FourSlashInterface.Cancellation(state); + const f = eval(wrappedCode); + f(test, goTo, verify, edit, debug, format, cancellation, FourSlashInterface.Classification, FourSlash.verifyOperationIsCancelled); } catch (err) { // Debugging: FourSlash.currentTestState.printCurrentFileState(); @@ -2660,3 +2650,628 @@ namespace FourSlash { }; } } + +namespace FourSlashInterface { + export class Test { + constructor(private state: FourSlash.TestState) { + } + + public markers(): FourSlash.Marker[] { + return this.state.getMarkers(); + } + + public marker(name?: string): FourSlash.Marker { + return this.state.getMarkerByName(name); + } + + public ranges(): FourSlash.Range[] { + return this.state.getRanges(); + } + + public markerByName(s: string): FourSlash.Marker { + return this.state.getMarkerByName(s); + } + } + + export class GoTo { + constructor(private state: FourSlash.TestState) { + } + // Moves the caret to the specified marker, + // or the anonymous marker ('/**/') if no name + // is given + public marker(name?: string) { + this.state.goToMarker(name); + } + + public bof() { + this.state.goToBOF(); + } + + public eof() { + this.state.goToEOF(); + } + + public definition(definitionIndex = 0) { + this.state.goToDefinition(definitionIndex); + } + + public type(definitionIndex = 0) { + this.state.goToTypeDefinition(definitionIndex); + } + + public position(position: number, fileIndex?: number): void; + public position(position: number, fileName?: string): void; + public position(position: number, fileNameOrIndex?: any): void { + if (fileNameOrIndex !== undefined) { + this.file(fileNameOrIndex); + } + this.state.goToPosition(position); + } + + // 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, content?: string): void; + public file(name: string, content?: string): void; + public file(indexOrName: any, content?: string): void { + this.state.openFile(indexOrName, content); + } + } + + export class VerifyNegatable { + public not: VerifyNegatable; + + constructor(protected state: FourSlash.TestState, private negative = false) { + if (!negative) { + this.not = new VerifyNegatable(state, true); + } + } + + // Verifies the member list contains the specified symbol. The + // member list is brought up if necessary + public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) { + if (this.negative) { + this.state.verifyMemberListDoesNotContain(symbol); + } + else { + this.state.verifyMemberListContains(symbol, text, documenation, kind); + } + } + + public memberListCount(expectedCount: number) { + this.state.verifyMemberListCount(expectedCount, this.negative); + } + + // Verifies the completion list contains the specified symbol. The + // completion list is brought up if necessary + public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { + if (this.negative) { + this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind); + } + else { + this.state.verifyCompletionListContains(symbol, text, documentation, kind); + } + } + + // Verifies the completion list items count to be greater than the specified amount. The + // completion list is brought up if necessary + public completionListItemsCountIsGreaterThan(count: number) { + this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); + } + + public completionListIsEmpty() { + this.state.verifyCompletionListIsEmpty(this.negative); + } + + public completionListAllowsNewIdentifier() { + this.state.verifyCompletionListAllowsNewIdentifier(this.negative); + } + + public memberListIsEmpty() { + this.state.verifyMemberListIsEmpty(this.negative); + } + + public referencesCountIs(count: number) { + this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false); + } + + public referencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) { + this.state.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); + } + + public signatureHelpPresent() { + this.state.verifySignatureHelpPresent(!this.negative); + } + + public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { + this.state.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); + } + + public errorExistsAfterMarker(markerName = "") { + this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ true); + } + + public errorExistsBeforeMarker(markerName = "") { + this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false); + } + + public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { + this.state.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation); + } + + public quickInfoExists() { + this.state.verifyQuickInfoExists(this.negative); + } + + public definitionCountIs(expectedCount: number) { + this.state.verifyDefinitionsCount(this.negative, expectedCount); + } + + public typeDefinitionCountIs(expectedCount: number) { + this.state.verifyTypeDefinitionsCount(this.negative, expectedCount); + } + + public definitionLocationExists() { + this.state.verifyDefinitionLocationExists(this.negative); + } + + public verifyDefinitionsName(name: string, containerName: string) { + this.state.verifyDefinitionsName(this.negative, name, containerName); + } + } + + export class Verify extends VerifyNegatable { + constructor(state: FourSlash.TestState) { + super(state); + } + + public caretAtMarker(markerName?: string) { + this.state.verifyCaretAtMarker(markerName); + } + + public indentationIs(numberOfSpaces: number) { + this.state.verifyIndentationAtCurrentPosition(numberOfSpaces); + } + + public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = ts.IndentStyle.Smart) { + this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle); + } + + public textAtCaretIs(text: string) { + this.state.verifyTextAtCaretIs(text); + } + + /** + * Compiles the current file and evaluates 'expr' in a context containing + * the emitted output, then compares (using ===) the result of that expression + * to 'value'. Do not use this function with external modules as it is not supported. + */ + public eval(expr: string, value: any) { + this.state.verifyEval(expr, value); + } + + public currentLineContentIs(text: string) { + this.state.verifyCurrentLineContent(text); + } + + public currentFileContentIs(text: string) { + this.state.verifyCurrentFileContent(text); + } + + public verifyGetEmitOutputForCurrentFile(expected: string): void { + this.state.verifyGetEmitOutputForCurrentFile(expected); + } + + public currentParameterHelpArgumentNameIs(name: string) { + this.state.verifyCurrentParameterHelpName(name); + } + + public currentParameterSpanIs(parameter: string) { + this.state.verifyCurrentParameterSpanIs(parameter); + } + + public currentParameterHelpArgumentDocCommentIs(docComment: string) { + this.state.verifyCurrentParameterHelpDocComment(docComment); + } + + public currentSignatureHelpDocCommentIs(docComment: string) { + this.state.verifyCurrentSignatureHelpDocComment(docComment); + } + + public signatureHelpCountIs(expected: number) { + this.state.verifySignatureHelpCount(expected); + } + + public signatureHelpArgumentCountIs(expected: number) { + this.state.verifySignatureHelpArgumentCount(expected); + } + + public currentSignatureParameterCountIs(expected: number) { + this.state.verifyCurrentSignatureHelpParameterCount(expected); + } + + public currentSignatureHelpIs(expected: string) { + this.state.verifyCurrentSignatureHelpIs(expected); + } + + public numberOfErrorsInCurrentFile(expected: number) { + this.state.verifyNumberOfErrorsInCurrentFile(expected); + } + + public baselineCurrentFileBreakpointLocations() { + this.state.baselineCurrentFileBreakpointLocations(); + } + + public baselineCurrentFileNameOrDottedNameSpans() { + this.state.baselineCurrentFileNameOrDottedNameSpans(); + } + + public baselineGetEmitOutput() { + this.state.baselineGetEmitOutput(); + } + + public nameOrDottedNameSpanTextIs(text: string) { + this.state.verifyCurrentNameOrDottedNameSpanText(text); + } + + public outliningSpansInCurrentFile(spans: FourSlash.TextSpan[]) { + this.state.verifyOutliningSpans(spans); + } + + public todoCommentsInCurrentFile(descriptors: string[]) { + this.state.verifyTodoComments(descriptors, this.state.getRanges()); + } + + public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { + this.state.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); + } + + public noMatchingBracePositionInCurrentFile(bracePosition: number) { + this.state.verifyNoMatchingBracePosition(bracePosition); + } + + public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { + this.state.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); + } + + public noDocCommentTemplate() { + this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); + } + + public getScriptLexicalStructureListCount(count: number) { + this.state.verifyGetScriptLexicalStructureListCount(count); + } + + // TODO: figure out what to do with the unused arguments. + public getScriptLexicalStructureListContains( + name: string, + kind: string, + fileName?: string, + parentName?: string, + isAdditionalSpan?: boolean, + markerPosition?: number) { + this.state.verifyGetScriptLexicalStructureListContains(name, kind); + } + + public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { + this.state.verifyNavigationItemsCount(count, searchValue, matchKind); + } + + public navigationItemsListContains( + name: string, + kind: string, + searchValue: string, + matchKind: string, + fileName?: string, + parentName?: string) { + this.state.verifyNavigationItemsListContains( + name, + kind, + searchValue, + matchKind, + fileName, + parentName); + } + + public occurrencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) { + this.state.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); + } + + public occurrencesAtPositionCount(expectedCount: number) { + this.state.verifyOccurrencesAtPositionListCount(expectedCount); + } + + public documentHighlightsAtPositionContains(range: FourSlash.Range, fileNamesToSearch: string[], kind?: string) { + this.state.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind); + } + + public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) { + this.state.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch); + } + + public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) { + this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind); + } + + /** + * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. + */ + public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) { + this.state.verifySyntacticClassifications(classifications); + } + + /** + * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. + */ + public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: FourSlash.TextSpan }[]) { + this.state.verifySemanticClassifications(classifications); + } + + public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) { + this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers); + } + + public renameInfoFailed(message?: string) { + this.state.verifyRenameInfoFailed(message); + } + + public renameLocations(findInStrings: boolean, findInComments: boolean) { + this.state.verifyRenameLocations(findInStrings, findInComments); + } + + public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, + displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { + this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); + } + + public getSyntacticDiagnostics(expected: string) { + this.state.getSyntacticDiagnostics(expected); + } + + public getSemanticDiagnostics(expected: string) { + this.state.getSemanticDiagnostics(expected); + } + + public ProjectInfo(expected: string []) { + this.state.verifyProjectInfo(expected); + } + } + + export class Edit { + constructor(private state: FourSlash.TestState) { + } + public backspace(count?: number) { + this.state.deleteCharBehindMarker(count); + } + + public deleteAtCaret(times?: number) { + this.state.deleteChar(times); + } + + public replace(start: number, length: number, text: string) { + this.state.replace(start, length, text); + } + + public paste(text: string) { + this.state.paste(text); + } + + public insert(text: string) { + this.insertLines(text); + } + + public insertLine(text: string) { + this.insertLines(text + "\n"); + } + + public insertLines(...lines: string[]) { + this.state.type(lines.join("\n")); + } + + public moveRight(count?: number) { + this.state.moveCaretRight(count); + } + + public moveLeft(count?: number) { + if (typeof count === "undefined") { + count = 1; + } + this.state.moveCaretRight(count * -1); + } + + public enableFormatting() { + this.state.enableFormatting = true; + } + + public disableFormatting() { + this.state.enableFormatting = false; + } + } + + export class Debug { + constructor(private state: FourSlash.TestState) { + } + + public printCurrentParameterHelp() { + this.state.printCurrentParameterHelp(); + } + + public printCurrentFileState() { + this.state.printCurrentFileState(); + } + + public printCurrentFileStateWithWhitespace() { + this.state.printCurrentFileState(/*makeWhitespaceVisible*/true); + } + + public printCurrentFileStateWithoutCaret() { + this.state.printCurrentFileState(/*makeWhitespaceVisible*/false, /*makeCaretVisible*/false); + } + + public printCurrentQuickInfo() { + this.state.printCurrentQuickInfo(); + } + + public printCurrentSignatureHelp() { + this.state.printCurrentSignatureHelp(); + } + + public printMemberListMembers() { + this.state.printMemberListMembers(); + } + + public printCompletionListMembers() { + this.state.printCompletionListMembers(); + } + + public printBreakpointLocation(pos: number) { + this.state.printBreakpointLocation(pos); + } + public printBreakpointAtCurrentLocation() { + this.state.printBreakpointAtCurrentLocation(); + } + + public printNameOrDottedNameSpans(pos: number) { + this.state.printNameOrDottedNameSpans(pos); + } + + public printErrorList() { + this.state.printErrorList(); + } + + public printNavigationItems(searchValue = ".*") { + this.state.printNavigationItems(searchValue); + } + + public printScriptLexicalStructureItems() { + this.state.printScriptLexicalStructureItems(); + } + + public printReferences() { + this.state.printReferences(); + } + + public printContext() { + this.state.printContext(); + } + } + + export class Format { + constructor(private state: FourSlash.TestState) { + } + + public document() { + this.state.formatDocument(); + } + + public copyFormatOptions(): ts.FormatCodeOptions { + return this.state.copyFormatOptions(); + } + + public setFormatOptions(options: ts.FormatCodeOptions) { + return this.state.setFormatOptions(options); + } + + public selection(startMarker: string, endMarker: string) { + this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position); + } + + public setOption(name: string, value: number): void; + public setOption(name: string, value: string): void; + public setOption(name: string, value: boolean): void; + public setOption(name: string, value: any): void { + this.state.formatCodeOptions[name] = value; + } + } + + export class Cancellation { + constructor(private state: FourSlash.TestState) { + } + + public resetCancelled() { + this.state.resetCancelled(); + } + + public setCancelled(numberOfCalls = 0) { + this.state.setCancelled(numberOfCalls); + } + } + + export namespace Classification { + export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("comment", text, position); + } + + export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("identifier", text, position); + } + + export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("keyword", text, position); + } + + export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("numericLiteral", text, position); + } + + export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("operator", text, position); + } + + export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("stringLiteral", text, position); + } + + export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("whiteSpace", text, position); + } + + export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("text", text, position); + } + + export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("punctuation", text, position); + } + + export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("docCommentTagName", text, position); + } + + export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("className", text, position); + } + + export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("enumName", text, position); + } + + export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("interfaceName", text, position); + } + + export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("moduleName", text, position); + } + + export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("typeParameterName", text, position); + } + + export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("parameterName", text, position); + } + + export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("typeAliasName", text, position); + } + + function getClassification(type: string, text: string, position?: number) { + return { + classificationType: type, + text: text, + textSpan: position === undefined ? undefined : { start: position, end: position + text.length } + }; + } + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts index 16d2efcd6d4..d66c1620751 100644 --- a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts +++ b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts @@ -3,16 +3,16 @@ //// var f4 = (x: T/**/ ) => { //// } -fs.goTo.marker(); +goTo.marker(); // Replace the "T" type with the non-existent type 'V'. -fs.edit.backspace(1); -fs.edit.insert("A"); +edit.backspace(1); +edit.insert("A"); // Bring up completion to force a pull resolve. This will end up resolving several symbols and // producing unreported diagnostics (i.e. that 'V' wasn't found). -fs.verify.completionListContains("T"); -fs.verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void"); +verify.completionListContains("T"); +verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void"); // There should now be a single error. -fs.verify.numberOfErrorsInCurrentFile(1); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(1); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index f6451e1f1c4..5b8bb94bb48 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -24,10 +24,7 @@ // @Module: Node // @Target: ES5 -// In the imperative section, you can write any valid TypeScript code. If -// you need help finding a something in Intellisense, you can -// type 'fs.' as an alternate way of accessing the top-level objects -// (e.g. 'fs.goTo.eof();') +// In the imperative section, you can write any valid TypeScript code. //--------------------------------------- // For API editors: @@ -45,52 +42,32 @@ // // TODO: figure out a better solution to the API exposure problem. -// /// -// /// - -declare var FourSlash; -module ts { - export interface SymbolDisplayPart { +declare module ts { + interface SymbolDisplayPart { text: string; kind: string; } + + enum IndentStyle { + None = 0, + Block = 1, + Smart = 2, + } } -//--------------------------------------------- - -// Return code used by getEmitOutput function to indicate status of the function -// It is a duplicate of the one in types.ts to expose it to testcases in fourslash -enum EmitReturnStatus { - Succeeded = 0, // All outputs generated if requested (.js, .map, .d.ts), no errors reported - AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, or compiler options errors, nothing generated - JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors - DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors - EmitErrorsEncountered = 4 // Emitter errors occurred during emitting process -} - -// This is a duplicate of the indentstyle in services.ts to expose it to testcases in fourslash -enum IndentStyle { - None, - Block, - Smart, -} - -module FourSlashInterface { - - export interface Marker { +declare module FourSlashInterface { + interface Marker { fileName: string; position: number; data?: any; } - - export interface EditorOptions { + interface EditorOptions { IndentSize: number; TabSize: number; NewLineCharacter: string; ConvertTabsToSpaces: boolean; } - - export interface FormatCodeOptions extends EditorOptions { + interface FormatCodeOptions extends EditorOptions { InsertSpaceAfterCommaDelimiter: boolean; InsertSpaceAfterSemicolonInForStatements: boolean; InsertSpaceBeforeAndAfterBinaryOperators: boolean; @@ -100,646 +77,275 @@ module FourSlashInterface { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } - - export interface Range { + interface Range { fileName: string; start: number; end: number; marker?: Marker; } - - export interface TextSpan { + interface TextSpan { start: number; end: number; } - - export class test_ { - public markers(): Marker[] { - return FourSlash.currentTestState.getMarkers(); - } - - public marker(name?: string): Marker { - return FourSlash.currentTestState.getMarkerByName(name); - } - - public ranges(): Range[] { - return FourSlash.currentTestState.getRanges(); - } - - public markerByName(s: string): Marker { - return FourSlash.currentTestState.getMarkerByName(s); - } + class test_ { + markers(): Marker[]; + marker(name?: string): Marker; + ranges(): Range[]; + markerByName(s: string): Marker; } - - export class goTo { - // Moves the caret to the specified marker, - // or the anonymous marker ('/**/') if no name - // is given - public marker(name?: string) { - FourSlash.currentTestState.goToMarker(name); - } - - public bof() { - FourSlash.currentTestState.goToBOF(); - } - - public eof() { - FourSlash.currentTestState.goToEOF(); - } - - public definition(definitionIndex: number = 0) { - FourSlash.currentTestState.goToDefinition(definitionIndex); - } - - public type(definitionIndex: number = 0) { - FourSlash.currentTestState.goToTypeDefinition(definitionIndex); - } - - public position(position: number, fileIndex?: number); - public position(position: number, fileName?: string); - public position(position: number, fileNameOrIndex?: any) { - if (fileNameOrIndex !== undefined) { - this.file(fileNameOrIndex); - } - FourSlash.currentTestState.goToPosition(position); - } - - // 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, content?: string); - public file(name: string, content?: string); - public file(indexOrName: any, content?: string) { - FourSlash.currentTestState.openFile(indexOrName, content); - } + class goTo { + marker(name?: string): void; + bof(): void; + eof(): void; + definition(definitionIndex?: number): void; + type(definitionIndex?: number): void; + position(position: number, fileIndex?: number): any; + position(position: number, fileName?: string): any; + file(index: number, content?: string): any; + file(name: string, content?: string): any; } - - export class verifyNegatable { - public not: verifyNegatable; - - constructor(private negative = false) { - if (!negative) { - this.not = new verifyNegatable(true); - } - } - - // Verifies the member list contains the specified symbol. The - // member list is brought up if necessary - public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) { - if (this.negative) { - FourSlash.currentTestState.verifyMemberListDoesNotContain(symbol); - } else { - FourSlash.currentTestState.verifyMemberListContains(symbol, text, documenation, kind); - } - } - - public memberListCount(expectedCount: number) { - FourSlash.currentTestState.verifyMemberListCount(expectedCount, this.negative); - } - - // Verifies the completion list contains the specified symbol. The - // completion list is brought up if necessary - public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { - if (this.negative) { - FourSlash.currentTestState.verifyCompletionListDoesNotContain(symbol, text, documentation, kind); - } else { - FourSlash.currentTestState.verifyCompletionListContains(symbol, text, documentation, kind); - } - } - - // Verifies the completion list items count to be greater than the specified amount. The - // completion list is brought up if necessary - public completionListItemsCountIsGreaterThan(count: number) { - FourSlash.currentTestState.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); - } - - public completionListIsEmpty() { - FourSlash.currentTestState.verifyCompletionListIsEmpty(this.negative); - } - - public completionListAllowsNewIdentifier() { - FourSlash.currentTestState.verifyCompletionListAllowsNewIdentifier(this.negative); - } - - public memberListIsEmpty() { - FourSlash.currentTestState.verifyMemberListIsEmpty(this.negative); - } - - public referencesCountIs(count: number) { - FourSlash.currentTestState.verifyReferencesCountIs(count, /*localFilesOnly*/ false); - } - - public referencesAtPositionContains(range: Range, isWriteAccess?: boolean) { - FourSlash.currentTestState.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); - } - - public signatureHelpPresent() { - FourSlash.currentTestState.verifySignatureHelpPresent(!this.negative); - } - - public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { - FourSlash.currentTestState.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); - } - - public errorExistsAfterMarker(markerName = "") { - FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, true); - } - - public errorExistsBeforeMarker(markerName = "") { - FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, false); - } - - public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { - FourSlash.currentTestState.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation); - } - - public quickInfoExists() { - FourSlash.currentTestState.verifyQuickInfoExists(this.negative); - } - - public definitionCountIs(expectedCount: number) { - FourSlash.currentTestState.verifyDefinitionsCount(this.negative, expectedCount); - } - - public typeDefinitionCountIs(expectedCount: number) { - FourSlash.currentTestState.verifyTypeDefinitionsCount(this.negative, expectedCount); - } - - public definitionLocationExists() { - FourSlash.currentTestState.verifyDefinitionLocationExists(this.negative); - } - - public verifyDefinitionsName(name: string, containerName: string) { - FourSlash.currentTestState.verifyDefinitionsName(this.negative, name, containerName); - } + class verifyNegatable { + private negative; + not: verifyNegatable; + constructor(negative?: boolean); + memberListContains(symbol: string, text?: string, documenation?: string, kind?: string): void; + memberListCount(expectedCount: number): void; + completionListContains(symbol: string, text?: string, documentation?: string, kind?: string): void; + completionListItemsCountIsGreaterThan(count: number): void; + completionListIsEmpty(): void; + completionListAllowsNewIdentifier(): void; + memberListIsEmpty(): void; + referencesCountIs(count: number): void; + referencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; + signatureHelpPresent(): void; + errorExistsBetweenMarkers(startMarker: string, endMarker: string): void; + errorExistsAfterMarker(markerName?: string): void; + errorExistsBeforeMarker(markerName?: string): void; + quickInfoIs(expectedText?: string, expectedDocumentation?: string): void; + quickInfoExists(): void; + definitionCountIs(expectedCount: number): void; + typeDefinitionCountIs(expectedCount: number): void; + definitionLocationExists(): void; + verifyDefinitionsName(name: string, containerName: string): void; } - - export class verify extends verifyNegatable { - public caretAtMarker(markerName?: string) { - FourSlash.currentTestState.verifyCaretAtMarker(markerName); - } - - public indentationIs(numberOfSpaces: number) { - FourSlash.currentTestState.verifyIndentationAtCurrentPosition(numberOfSpaces); - } - - public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = IndentStyle.Smart) { - FourSlash.currentTestState.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle); - } - - public textAtCaretIs(text: string) { - FourSlash.currentTestState.verifyTextAtCaretIs(text); - } - + class verify extends verifyNegatable { + caretAtMarker(markerName?: string): void; + indentationIs(numberOfSpaces: number): void; + indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: IndentStyle): void; + textAtCaretIs(text: string): void; /** * Compiles the current file and evaluates 'expr' in a context containing * the emitted output, then compares (using ===) the result of that expression * to 'value'. Do not use this function with external modules as it is not supported. */ - public eval(expr: string, value: any) { - FourSlash.currentTestState.verifyEval(expr, value); - } - - public currentLineContentIs(text: string) { - FourSlash.currentTestState.verifyCurrentLineContent(text); - } - - public currentFileContentIs(text: string) { - FourSlash.currentTestState.verifyCurrentFileContent(text); - } - - public verifyGetEmitOutputForCurrentFile(expected: string): void { - FourSlash.currentTestState.verifyGetEmitOutputForCurrentFile(expected); - } - - public currentParameterHelpArgumentNameIs(name: string) { - FourSlash.currentTestState.verifyCurrentParameterHelpName(name); - } - - public currentParameterSpanIs(parameter: string) { - FourSlash.currentTestState.verifyCurrentParameterSpanIs(parameter); - } - - public currentParameterHelpArgumentDocCommentIs(docComment: string) { - FourSlash.currentTestState.verifyCurrentParameterHelpDocComment(docComment); - } - - public currentSignatureHelpDocCommentIs(docComment: string) { - FourSlash.currentTestState.verifyCurrentSignatureHelpDocComment(docComment); - } - - public signatureHelpCountIs(expected: number) { - FourSlash.currentTestState.verifySignatureHelpCount(expected); - } - - public signatureHelpArgumentCountIs(expected: number) { - FourSlash.currentTestState.verifySignatureHelpArgumentCount(expected); - } - - public currentSignatureParameterCountIs(expected: number) { - FourSlash.currentTestState.verifyCurrentSignatureHelpParameterCount(expected); - } - - public currentSignatureTypeParameterCountIs(expected: number) { - FourSlash.currentTestState.verifyCurrentSignatureHelpTypeParameterCount(expected); - } - - public currentSignatureHelpIs(expected: string) { - FourSlash.currentTestState.verifyCurrentSignatureHelpIs(expected); - } - - public numberOfErrorsInCurrentFile(expected: number) { - FourSlash.currentTestState.verifyNumberOfErrorsInCurrentFile(expected); - } - - public baselineCurrentFileBreakpointLocations() { - FourSlash.currentTestState.baselineCurrentFileBreakpointLocations(); - } - - public baselineCurrentFileNameOrDottedNameSpans() { - FourSlash.currentTestState.baselineCurrentFileNameOrDottedNameSpans(); - } - - public baselineGetEmitOutput() { - FourSlash.currentTestState.baselineGetEmitOutput(); - } - - public nameOrDottedNameSpanTextIs(text: string) { - FourSlash.currentTestState.verifyCurrentNameOrDottedNameSpanText(text); - } - - public outliningSpansInCurrentFile(spans: TextSpan[]) { - FourSlash.currentTestState.verifyOutliningSpans(spans); - } - - public todoCommentsInCurrentFile(descriptors: string[]) { - FourSlash.currentTestState.verifyTodoComments(descriptors, test.ranges()); - } - - public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { - FourSlash.currentTestState.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); - } - - public noMatchingBracePositionInCurrentFile(bracePosition: number) { - FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition); - } - - public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { - FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); - } - - public noDocCommentTemplate() { - this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); - } - - public getScriptLexicalStructureListCount(count: number) { - FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count); - } - - // TODO: figure out what to do with the unused arguments. - public getScriptLexicalStructureListContains( - name: string, - kind: string, - fileName?: string, - parentName?: string, - isAdditionalSpan?: boolean, - markerPosition?: number) { - FourSlash.currentTestState.verifyGetScriptLexicalStructureListContains(name, kind); - } - - public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { - FourSlash.currentTestState.verifyNavigationItemsCount(count, searchValue, matchKind); - } - - public navigationItemsListContains( - name: string, - kind: string, - searchValue: string, - matchKind: string, - fileName?: string, - parentName?: string) { - FourSlash.currentTestState.verifyNavigationItemsListContains( - name, - kind, - searchValue, - matchKind, - fileName, - parentName); - } - - public occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean) { - FourSlash.currentTestState.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); - } - - public occurrencesAtPositionCount(expectedCount: number) { - FourSlash.currentTestState.verifyOccurrencesAtPositionListCount(expectedCount); - } - - public documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string) { - FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind); - } - - public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) { - FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch); - } - - public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) { - FourSlash.currentTestState.verifyCompletionEntryDetails(entryName, text, documentation, kind); - } - + eval(expr: string, value: any): void; + currentLineContentIs(text: string): void; + currentFileContentIs(text: string): void; + verifyGetEmitOutputForCurrentFile(expected: string): void; + currentParameterHelpArgumentNameIs(name: string): void; + currentParameterSpanIs(parameter: string): void; + currentParameterHelpArgumentDocCommentIs(docComment: string): void; + currentSignatureHelpDocCommentIs(docComment: string): void; + signatureHelpCountIs(expected: number): void; + signatureHelpArgumentCountIs(expected: number): void; + currentSignatureParameterCountIs(expected: number): void; + currentSignatureTypeParameterCountIs(expected: number): void; + currentSignatureHelpIs(expected: string): void; + numberOfErrorsInCurrentFile(expected: number): void; + baselineCurrentFileBreakpointLocations(): void; + baselineCurrentFileNameOrDottedNameSpans(): void; + baselineGetEmitOutput(): void; + nameOrDottedNameSpanTextIs(text: string): void; + outliningSpansInCurrentFile(spans: TextSpan[]): void; + todoCommentsInCurrentFile(descriptors: string[]): void; + matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void; + noMatchingBracePositionInCurrentFile(bracePosition: number): void; + DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void; + noDocCommentTemplate(): void; + getScriptLexicalStructureListCount(count: number): void; + getScriptLexicalStructureListContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void; + navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void; + navigationItemsListContains(name: string, kind: string, searchValue: string, matchKind: string, fileName?: string, parentName?: string): void; + occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; + occurrencesAtPositionCount(expectedCount: number): void; + documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string): void; + documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]): void; + completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string): void; /** * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. */ - public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) { - FourSlash.currentTestState.verifySyntacticClassifications(classifications); - } - + syntacticClassificationsAre(...classifications: { + classificationType: string; + text: string; + }[]): void; /** * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. */ - public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: TextSpan }[]) { - FourSlash.currentTestState.verifySemanticClassifications(classifications); - } - - public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) { - FourSlash.currentTestState.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers) - } - - public renameInfoFailed(message?: string) { - FourSlash.currentTestState.verifyRenameInfoFailed(message) - } - - public renameLocations(findInStrings: boolean, findInComments: boolean) { - FourSlash.currentTestState.verifyRenameLocations(findInStrings, findInComments); - } - - public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, - displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { - FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); - } - - public getSyntacticDiagnostics(expected: string) { - FourSlash.currentTestState.getSyntacticDiagnostics(expected); - } - - public getSemanticDiagnostics(expected: string) { - FourSlash.currentTestState.getSemanticDiagnostics(expected); - } - - public ProjectInfo(expected: string []) { - FourSlash.currentTestState.verifyProjectInfo(expected); - } + semanticClassificationsAre(...classifications: { + classificationType: string; + text: string; + textSpan?: TextSpan; + }[]): void; + renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string): void; + renameInfoFailed(message?: string): void; + renameLocations(findInStrings: boolean, findInComments: boolean): void; + verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { + start: number; + length: number; + }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]): void; + getSyntacticDiagnostics(expected: string): void; + getSemanticDiagnostics(expected: string): void; + ProjectInfo(expected: string[]): void; } - - export class edit { - public backspace(count?: number) { - FourSlash.currentTestState.deleteCharBehindMarker(count); - } - - public deleteAtCaret(times?: number) { - FourSlash.currentTestState.deleteChar(times); - } - - public replace(start: number, length: number, text: string) { - FourSlash.currentTestState.replace(start, length, text); - } - - public paste(text: string) { - FourSlash.currentTestState.paste(text); - } - - public insert(text: string) { - this.insertLines(text); - } - - public insertLine(text: string) { - this.insertLines(text + '\n'); - } - - public insertLines(...lines: string[]) { - FourSlash.currentTestState.type(lines.join('\n')); - } - - public moveRight(count?: number) { - FourSlash.currentTestState.moveCaretRight(count); - } - - public moveLeft(count?: number) { - if (typeof count === 'undefined') { - count = 1; - } - FourSlash.currentTestState.moveCaretRight(count * -1); - } - - public enableFormatting() { - FourSlash.currentTestState.enableFormatting = true; - } - - public disableFormatting() { - FourSlash.currentTestState.enableFormatting = false; - } + class edit { + backspace(count?: number): void; + deleteAtCaret(times?: number): void; + replace(start: number, length: number, text: string): void; + paste(text: string): void; + insert(text: string): void; + insertLine(text: string): void; + insertLines(...lines: string[]): void; + moveRight(count?: number): void; + moveLeft(count?: number): void; + enableFormatting(): void; + disableFormatting(): void; } - - export class debug { - public printCurrentParameterHelp() { - FourSlash.currentTestState.printCurrentParameterHelp(); - } - - public printCurrentFileState() { - FourSlash.currentTestState.printCurrentFileState(); - } - - public printCurrentFileStateWithWhitespace() { - FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/true); - } - - public printCurrentFileStateWithoutCaret() { - FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/false, /*withCaret=*/false); - } - - public printCurrentQuickInfo() { - FourSlash.currentTestState.printCurrentQuickInfo(); - } - - public printCurrentSignatureHelp() { - FourSlash.currentTestState.printCurrentSignatureHelp(); - } - - public printMemberListMembers() { - FourSlash.currentTestState.printMemberListMembers(); - } - - public printCompletionListMembers() { - FourSlash.currentTestState.printCompletionListMembers(); - } - - public printBreakpointLocation(pos: number) { - FourSlash.currentTestState.printBreakpointLocation(pos); - } - public printBreakpointAtCurrentLocation() { - FourSlash.currentTestState.printBreakpointAtCurrentLocation(); - } - - public printNameOrDottedNameSpans(pos: number) { - FourSlash.currentTestState.printNameOrDottedNameSpans(pos); - } - - public printErrorList() { - FourSlash.currentTestState.printErrorList(); - } - - public printNavigationItems(searchValue: string = ".*") { - FourSlash.currentTestState.printNavigationItems(searchValue); - } - - public printScriptLexicalStructureItems() { - FourSlash.currentTestState.printScriptLexicalStructureItems(); - } - - public printReferences() { - FourSlash.currentTestState.printReferences(); - } - - public printContext() { - FourSlash.currentTestState.printContext(); - } + class debug { + printCurrentParameterHelp(): void; + printCurrentFileState(): void; + printCurrentFileStateWithWhitespace(): void; + printCurrentFileStateWithoutCaret(): void; + printCurrentQuickInfo(): void; + printCurrentSignatureHelp(): void; + printMemberListMembers(): void; + printCompletionListMembers(): void; + printBreakpointLocation(pos: number): void; + printBreakpointAtCurrentLocation(): void; + printNameOrDottedNameSpans(pos: number): void; + printErrorList(): void; + printNavigationItems(searchValue?: string): void; + printScriptLexicalStructureItems(): void; + printReferences(): void; + printContext(): void; } - - export class format { - public document() { - FourSlash.currentTestState.formatDocument(); - } - - public copyFormatOptions(): FormatCodeOptions { - return FourSlash.currentTestState.copyFormatOptions(); - } - - public setFormatOptions(options: FormatCodeOptions) { - return FourSlash.currentTestState.setFormatOptions(options); - } - - public selection(startMarker: string, endMarker: string) { - FourSlash.currentTestState.formatSelection(FourSlash.currentTestState.getMarkerByName(startMarker).position, FourSlash.currentTestState.getMarkerByName(endMarker).position); - } - - public setOption(name: string, value: number); - public setOption(name: string, value: string); - public setOption(name: string, value: boolean); - public setOption(name: string, value: any) { - FourSlash.currentTestState.formatCodeOptions[name] = value; - } + class format { + document(): void; + copyFormatOptions(): FormatCodeOptions; + setFormatOptions(options: FormatCodeOptions): any; + selection(startMarker: string, endMarker: string): void; + setOption(name: string, value: number): any; + setOption(name: string, value: string): any; + setOption(name: string, value: boolean): any; } - - export class cancellation { - public resetCancelled() { - FourSlash.currentTestState.resetCancelled(); - } - - public setCancelled(numberOfCalls: number = 0) { - FourSlash.currentTestState.setCancelled(numberOfCalls); - } + class cancellation { + resetCancelled(): void; + setCancelled(numberOfCalls?: number): void; } - - export module classification { - export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("comment", text, position); - } - - export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("identifier", text, position); - } - - export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("keyword", text, position); - } - - export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("numericLiteral", text, position); - } - - export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("operator", text, position); - } - - export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("stringLiteral", text, position); - } - - export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("whiteSpace", text, position); - } - - export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("text", text, position); - } - - export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("punctuation", text, position); - } - - export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("docCommentTagName", text, position); - } - - export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("className", text, position); - } - - export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("enumName", text, position); - } - - export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("interfaceName", text, position); - } - - export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("moduleName", text, position); - } - - export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("typeParameterName", text, position); - } - - export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("parameterName", text, position); - } - - export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("typeAliasName", text, position); - } - - function getClassification(type: string, text: string, position?: number) { - return { - classificationType: type, - text: text, - textSpan: position === undefined ? undefined : { start: position, end: position + text.length } - }; - } + module classification { + function comment(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function identifier(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function keyword(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function numericLiteral(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function operator(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function stringLiteral(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function whiteSpace(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function text(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function punctuation(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function docCommentTagName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function className(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function enumName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function interfaceName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function moduleName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function typeParameterName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function parameterName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function typeAliasName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; } } - -module fs { - export var test = new FourSlashInterface.test_(); - export var goTo = new FourSlashInterface.goTo(); - export var verify = new FourSlashInterface.verify(); - export var edit = new FourSlashInterface.edit(); - export var debug = new FourSlashInterface.debug(); - export var format = new FourSlashInterface.format(); - export var cancellation = new FourSlashInterface.cancellation(); +declare module fs { + var test: FourSlashInterface.test_; + var goTo: FourSlashInterface.goTo; + var verify: FourSlashInterface.verify; + var edit: FourSlashInterface.edit; + var debug: FourSlashInterface.debug; + var format: FourSlashInterface.format; + var cancellation: FourSlashInterface.cancellation; } - -function verifyOperationIsCancelled(f) { - FourSlash.verifyOperationIsCancelled(f); -} - -var test = new FourSlashInterface.test_(); -var goTo = new FourSlashInterface.goTo(); -var verify = new FourSlashInterface.verify(); -var edit = new FourSlashInterface.edit(); -var debug = new FourSlashInterface.debug(); -var format = new FourSlashInterface.format(); -var cancellation = new FourSlashInterface.cancellation(); -var classification = FourSlashInterface.classification; +declare function verifyOperationIsCancelled(f: any): void; +declare var test: FourSlashInterface.test_; +declare var goTo: FourSlashInterface.goTo; +declare var verify: FourSlashInterface.verify; +declare var edit: FourSlashInterface.edit; +declare var debug: FourSlashInterface.debug; +declare var format: FourSlashInterface.format; +declare var cancellation: FourSlashInterface.cancellation; +declare var classification: typeof FourSlashInterface.classification; diff --git a/tests/cases/fourslash/indentationBlock.ts b/tests/cases/fourslash/indentationBlock.ts index e880c4a0957..853ff43b0d6 100644 --- a/tests/cases/fourslash/indentationBlock.ts +++ b/tests/cases/fourslash/indentationBlock.ts @@ -179,5 +179,5 @@ ////{| "indent": 0 |} test.markers().forEach(marker => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.Block); + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.Block); }); diff --git a/tests/cases/fourslash/indentationNone.ts b/tests/cases/fourslash/indentationNone.ts index 078f5ab35f6..610a336cdda 100644 --- a/tests/cases/fourslash/indentationNone.ts +++ b/tests/cases/fourslash/indentationNone.ts @@ -179,5 +179,5 @@ ////{| "indent": 0 |} test.markers().forEach(marker => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.None); + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.None); }); diff --git a/tests/cases/fourslash/recursiveClassReference.ts b/tests/cases/fourslash/recursiveClassReference.ts index d0e96ac90e3..81843711d65 100644 --- a/tests/cases/fourslash/recursiveClassReference.ts +++ b/tests/cases/fourslash/recursiveClassReference.ts @@ -11,4 +11,4 @@ //// } goTo.marker(); -fs.verify.quickInfoExists(); +verify.quickInfoExists(); diff --git a/tests/cases/fourslash/renameModuleToVar.ts b/tests/cases/fourslash/renameModuleToVar.ts index 023b0fa1c74..fc31f4040e8 100644 --- a/tests/cases/fourslash/renameModuleToVar.ts +++ b/tests/cases/fourslash/renameModuleToVar.ts @@ -10,7 +10,7 @@ //// var z = y + 5; ////} -fs.goTo.marker(); -fs.edit.backspace(6); -fs.edit.insert("var"); -fs.verify.numberOfErrorsInCurrentFile(0); \ No newline at end of file +goTo.marker(); +edit.backspace(6); +edit.insert("var"); +verify.numberOfErrorsInCurrentFile(0); From 076d65e1cf261277692591c33c5f4978c57c36d1 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 16:23:18 -0800 Subject: [PATCH 82/93] addressed PR feedback --- src/harness/compilerRunner.ts | 7 ++++--- src/harness/harness.ts | 24 +++++++++++++----------- tests/cases/fourslash/fourslash.ts | 11 +---------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 85a51b8f2a4..399f8a272dd 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -250,10 +250,11 @@ class CompilerBaselineRunner extends RunnerBase { // These types are equivalent, but depend on what order the compiler observed // certain parts of the program. - const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)); + const program = result.program; + const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); - const fullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ true); - const pullWalker = new TypeWriterWalker(result.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 = {}; diff --git a/src/harness/harness.ts b/src/harness/harness.ts index e58e6635434..ef0f2678e29 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -767,9 +767,9 @@ namespace Harness { } namespace Harness { - const tcServicesFileName = "built/local/typescriptServices.js"; export const libFolder = "built/local/"; - export let tcServicesFile = IO.readFile(tcServicesFileName); + const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js"); + export const tcServicesFile = IO.readFile(tcServicesFileName); export interface SourceMapEmitterCallback { (emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void; @@ -990,7 +990,6 @@ namespace Harness { options.noErrorTruncation = true; options.skipDefaultLibCheck = true; - const newLine = "\r\n"; currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); // Parse settings @@ -1002,27 +1001,30 @@ namespace Harness { useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; } + const programFiles: TestFile[] = inputFiles.slice(); // 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: TestFile[] = []; if (options.includeBuiltFile) { - const builtFileName = libFolder + options.includeBuiltFile; + const builtFileName = ts.combinePaths(libFolder, options.includeBuiltFile); const builtFile: TestFile = { unitName: builtFileName, - content: normalizeLineEndings(IO.readFile(builtFileName), newLine), + content: normalizeLineEndings(IO.readFile(builtFileName), Harness.IO.newLine()), }; - includeBuiltFiles.push(builtFile); + programFiles.push(builtFile); } const fileOutputs: GeneratedFile[] = []; - const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); + const programFileNames = programFiles.map(file => file.unitName); const compilerHost = createCompilerHost( - inputFiles.concat(includeBuiltFiles).concat(otherFiles), + programFiles.concat(otherFiles), (fileName, code, writeByteOrderMark) => fileOutputs.push({ fileName, code, writeByteOrderMark }), - options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); - const program = ts.createProgram(programFiles, options, compilerHost); + options.target, + useCaseSensitiveFileNames, + currentDirectory, + options.newLine); + const program = ts.createProgram(programFileNames, options, compilerHost); const emitResult = program.emit(); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 5b8bb94bb48..f93ac76d6ed 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -55,7 +55,7 @@ declare module ts { } } -declare module FourSlashInterface { +declare namespace FourSlashInterface { interface Marker { fileName: string; position: number; @@ -331,15 +331,6 @@ declare module FourSlashInterface { }; } } -declare module fs { - var test: FourSlashInterface.test_; - var goTo: FourSlashInterface.goTo; - var verify: FourSlashInterface.verify; - var edit: FourSlashInterface.edit; - var debug: FourSlashInterface.debug; - var format: FourSlashInterface.format; - var cancellation: FourSlashInterface.cancellation; -} declare function verifyOperationIsCancelled(f: any): void; declare var test: FourSlashInterface.test_; declare var goTo: FourSlashInterface.goTo; From a275dabe44f1e58fb7676b963190dd70cd729ab6 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Nov 2015 16:48:57 -0800 Subject: [PATCH 83/93] When constructing signature, include parameter symbol instead of property symbol of parameter-property declaration Fixes #4566 --- src/compiler/checker.ts | 8 +++++++- ...natureHelpConstructorCallParamProperties.ts | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f975c110b03..378fd85265f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3829,7 +3829,13 @@ namespace ts { let minArgumentCount = -1; for (let i = 0, n = declaration.parameters.length; i < n; i++) { const param = declaration.parameters[i]; - parameters.push(param.symbol); + let paramSymbol = param.symbol; + // Include parameter symbol instead of property symbol in the signature + if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) { + const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); + paramSymbol = resolvedSymbol; + } + parameters.push(paramSymbol); if (param.type && param.type.kind === SyntaxKind.StringLiteral) { hasStringLiterals = true; } diff --git a/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts b/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts new file mode 100644 index 00000000000..aab276403fe --- /dev/null +++ b/tests/cases/fourslash/signatureHelpConstructorCallParamProperties.ts @@ -0,0 +1,18 @@ +/// + +////class Circle { +//// /** +//// * Initialize a circle. +//// * @param radius The radius of the circle. +//// */ +//// constructor(private radius: number) { +//// } +////} +////var a = new Circle(/**/ + +goTo.marker(''); +verify.signatureHelpCountIs(1); +verify.currentSignatureHelpIs("Circle(radius: number): Circle"); +verify.currentParameterHelpArgumentNameIs("radius"); +verify.currentParameterSpanIs("radius: number"); +verify.currentParameterHelpArgumentDocCommentIs("The radius of the circle."); \ No newline at end of file From 33fc598a8afe3189cf1593c7f081241c0bd43045 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 23:24:25 -0800 Subject: [PATCH 84/93] clean residual state in binder and emitter, clean test data in version cache test --- src/compiler/binder.ts | 2 + src/compiler/emitter.ts | 55 +++++----- tests/cases/unittests/versionCache.ts | 141 +++++++++++++++++--------- 3 files changed, 122 insertions(+), 76 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8b88da5b749..6b04e22551d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -139,6 +139,8 @@ namespace ts { file.classifiableNames = classifiableNames; } + file = undefined; + options = undefined; parent = undefined; container = undefined; blockScopeContainer = undefined; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e4cd57542a7..bdeac582bbf 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -516,7 +516,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi let decorateEmitted: boolean; let paramEmitted: boolean; let awaiterEmitted: boolean; - let tempFlags: TempFlags; + let tempFlags: TempFlags = 0; let tempVariables: Identifier[]; let tempParameters: Identifier[]; let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; @@ -584,33 +584,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return doEmit; function doEmit(jsFilePath: string, rootFile?: SourceFile) { - // reset the state - writer.reset(); - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; - exportFunctionForFile = undefined; generatedNameSet = {}; nodeToGeneratedName = []; - computedPropertyNamesToGeneratedNames = undefined; - convertedLoopState = undefined; - - extendsEmitted = false; - decorateEmitted = false; - paramEmitted = false; - awaiterEmitted = false; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStars = undefined; - detachedCommentsInfo = undefined; - sourceMapData = undefined; - isEs6Module = false; - renamedDependencies = undefined; - isCurrentFileExternalModule = false; root = rootFile; if (compilerOptions.sourceMap || compilerOptions.inlineSourceMap) { @@ -634,6 +609,34 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); writeEmittedFiles(writer.getText(), jsFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM); + + // reset the state + writer.reset(); + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + exportFunctionForFile = undefined; + generatedNameSet = undefined; + nodeToGeneratedName = undefined; + computedPropertyNamesToGeneratedNames = undefined; + convertedLoopState = undefined; + extendsEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + tempFlags = 0; + tempVariables = undefined; + tempParameters = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStars = undefined; + detachedCommentsInfo = undefined; + sourceMapData = undefined; + isEs6Module = false; + renamedDependencies = undefined; + isCurrentFileExternalModule = false; + root = undefined; } function emitSourceFile(sourceFile: SourceFile): void { diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index 06c2cadbfe9..20cb0ea7127 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -20,7 +20,10 @@ module ts { } describe('VersionCache TS code', () => { - var testContent = `/// + let validateEditAtLineCharIndex: (line: number, char: number, deleteLength: number, insertString: string) => void; + + before(() => { + let testContent = `/// var x = 10; var y = { zebra: 12, giraffe: "ell" }; z.a; @@ -31,16 +34,21 @@ k=y; var p:Point=new Point(); var q:Point=p;` - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + let {lines, lineMap} = server.LineIndex.linesFromText(testContent); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); + let lineIndex = new server.LineIndex(); + lineIndex.load(lines); - function validateEditAtLineCharIndex(line: number, char: number, deleteLength: number, insertString: string): void { - let position = lineColToPosition(lineIndex, line, char); - validateEdit(lineIndex, testContent, position, deleteLength, insertString); - } + validateEditAtLineCharIndex = (line: number, char: number, deleteLength: number, insertString: string) => { + let position = lineColToPosition(lineIndex, line, char); + validateEdit(lineIndex, testContent, position, deleteLength, insertString); + }; + }); + + after(() => { + validateEditAtLineCharIndex = undefined; + }) it('change 9 1 0 1 {"y"}', () => { validateEditAtLineCharIndex(9, 1, 0, "y"); @@ -68,22 +76,35 @@ var q:Point=p;` }); describe('VersionCache simple text', () => { - let testContent = `in this story: + let validateEditAtPosition: (position: number, deleteLength: number, insertString: string) => void; + let testContent: string; + let lines: string[]; + let lineMap: number[]; + before(() => { + testContent = `in this story: the lazy brown fox jumped over the cow that ate the grass that was purple at the tips and grew 1cm per day`; - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); + let lineIndex = new server.LineIndex(); + lineIndex.load(lines); - function validateEditAtPosition(position: number, deleteLength: number, insertString: string): void { - validateEdit(lineIndex, testContent, position, deleteLength, insertString); - } + validateEditAtPosition = (position: number, deleteLength: number, insertString: string) => { + validateEdit(lineIndex, testContent, position, deleteLength, insertString); + } + }); + + after(() => { + validateEditAtPosition = undefined; + testContent = undefined; + lines = undefined; + lineMap = undefined; + }); it('Insert at end of file', () => { validateEditAtPosition(testContent.length, 0, "hmmmm...\r\n"); @@ -159,50 +180,70 @@ and grew 1cm per day`; }); describe('VersionCache stress test', () => { - const iterationCount = 20; - //const interationCount = 20000; // uncomment for testing - - // Use scanner.ts, decent size, does not change frequentlly - let testFileName = "src/compiler/scanner.ts"; - let testContent = Harness.IO.readFile(testFileName); - let totalChars = testContent.length; - assert.isTrue(totalChars > 0, "Failed to read test file."); - - let {lines, lineMap} = server.LineIndex.linesFromText(testContent); - assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); - - let lineIndex = new server.LineIndex(); - lineIndex.load(lines); - let rsa: number[] = []; let la: number[] = []; let las: number[] = []; let elas: number[] = []; let ersa: number[] = []; let ela: number[] = []; - let etotalChars = totalChars; + const iterationCount = 20; + let lines: string[]; + let lineMap: number[]; + let lineIndex: server.LineIndex; + let testContent: string; - for (let j = 0; j < 100000; j++) { - rsa[j] = Math.floor(Math.random() * totalChars); - la[j] = Math.floor(Math.random() * (totalChars - rsa[j])); - if (la[j] > 4) { - las[j] = 4; - } - else { - las[j] = la[j]; - } - if (j < 4000) { - ersa[j] = Math.floor(Math.random() * etotalChars); - ela[j] = Math.floor(Math.random() * (etotalChars - ersa[j])); - if (ela[j] > 4) { - elas[j] = 4; + before(() => { + //const interationCount = 20000; // uncomment for testing + + // Use scanner.ts, decent size, does not change frequentlly + let testFileName = "src/compiler/scanner.ts"; + testContent = Harness.IO.readFile(testFileName); + let totalChars = testContent.length; + assert.isTrue(totalChars > 0, "Failed to read test file."); + + ({lines, lineMap} = server.LineIndex.linesFromText(testContent)); + assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line"); + + lineIndex = new server.LineIndex(); + lineIndex.load(lines); + + let etotalChars = totalChars; + + for (let j = 0; j < 100000; j++) { + rsa[j] = Math.floor(Math.random() * totalChars); + la[j] = Math.floor(Math.random() * (totalChars - rsa[j])); + if (la[j] > 4) { + las[j] = 4; } else { - elas[j] = ela[j]; + las[j] = la[j]; + } + if (j < 4000) { + ersa[j] = Math.floor(Math.random() * etotalChars); + ela[j] = Math.floor(Math.random() * (etotalChars - ersa[j])); + if (ela[j] > 4) { + elas[j] = 4; + } + else { + elas[j] = ela[j]; + } + etotalChars += (las[j] - elas[j]); } - etotalChars += (las[j] - elas[j]); } - } + }); + + after(() => { + rsa = undefined; + la = undefined; + las = undefined; + elas = undefined; + ersa = undefined; + ela = undefined; + lines = undefined; + lineMap = undefined; + lineIndex = undefined; + testContent = undefined; + }); it("Range (average length 1/4 file size)", () => { for (let i = 0; i < iterationCount; i++) { From a26d89d7a2ebb924f1f1bc519c94ac465899f8fa Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 23:44:07 -0800 Subject: [PATCH 85/93] addressed PR feedback --- tests/cases/unittests/versionCache.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/cases/unittests/versionCache.ts b/tests/cases/unittests/versionCache.ts index 20cb0ea7127..c1d283ca8cd 100644 --- a/tests/cases/unittests/versionCache.ts +++ b/tests/cases/unittests/versionCache.ts @@ -187,15 +187,14 @@ and grew 1cm per day`; let ersa: number[] = []; let ela: number[] = []; const iterationCount = 20; + //const iterationCount = 20000; // uncomment for testing let lines: string[]; let lineMap: number[]; let lineIndex: server.LineIndex; let testContent: string; before(() => { - //const interationCount = 20000; // uncomment for testing - - // Use scanner.ts, decent size, does not change frequentlly + // Use scanner.ts, decent size, does not change frequently let testFileName = "src/compiler/scanner.ts"; testContent = Harness.IO.readFile(testFileName); let totalChars = testContent.length; From a989595044bf942cef77360e7225622f464e4a6b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Nov 2015 11:24:17 -0800 Subject: [PATCH 86/93] use getCanonicalFileName on path fragments as in other utility methods --- src/compiler/program.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 80f793cb50f..dc31dfb5213 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -919,9 +919,8 @@ namespace ts { return; } - const caseSensitive = host.useCaseSensitiveFileNames(); for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (caseSensitive ? commonPathComponents[i] !== sourcePathComponents[i] : commonPathComponents[i].toLocaleLowerCase() !== sourcePathComponents[i].toLocaleLowerCase()) { + if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { if (i === 0) { // Failed to find any common path component return true; From e0a8af00a78d28c5b929835a5aceb623e032d6ea Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 17 Nov 2015 13:27:52 -0800 Subject: [PATCH 87/93] do not resolve parameters/type parameters if it is requested from restricted locations --- src/compiler/checker.ts | 36 ++++++++++--- ...rameterNamesInTypeParameterList.errors.txt | 44 +++++++++++++++ .../parameterNamesInTypeParameterList.js | 53 +++++++++++++++++++ ...ersAndParametersInComputedNames.errors.txt | 17 ++++++ ...eParametersAndParametersInComputedNames.js | 21 ++++++++ .../parameterNamesInTypeParameterList.ts | 23 ++++++++ ...eParametersAndParametersInComputedNames.ts | 8 +++ 7 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt create mode 100644 tests/baselines/reference/parameterNamesInTypeParameterList.js create mode 100644 tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt create mode 100644 tests/baselines/reference/typeParametersAndParametersInComputedNames.js create mode 100644 tests/cases/compiler/parameterNamesInTypeParameterList.ts create mode 100644 tests/cases/compiler/typeParametersAndParametersInComputedNames.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 378fd85265f..f9fd563b873 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -476,15 +476,37 @@ namespace ts { // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = getSymbol(location.locals, name, meaning)) { - // Type parameters of a function are in scope in the entire function declaration, including the parameter - // list and return type. However, local types are only in scope in the function body. - if (!(meaning & SymbolFlags.Type) || - !(result.flags & (SymbolFlags.Type & ~SymbolFlags.TypeParameter)) || - !isFunctionLike(location) || - lastLocation === (location).body) { + let useResult = true; + if (isFunctionLike(location) && lastLocation && lastLocation !== (location).body) { + // symbol lookup restrictions for function-like declarations + // - Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + // - parameters are only in the scope of function body + if (meaning & result.flags & SymbolFlags.Type) { + useResult = result.flags & SymbolFlags.TypeParameter + // type parameters are visible in parameter list, return type and type parameter list + ? lastLocation === (location).type || + lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.TypeParameter + // local types not visible outside the function body + : false; + } + if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { + // function scoped variables are visible only inside function body and parameter list + // technically here we might mix parameters and variables declared in function, + // however this case is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. + useResult = lastLocation === (location).type || + lastLocation.kind === SyntaxKind.Parameter; + } + } + + if (useResult) { break loop; } - result = undefined; + else { + result = undefined; + } } } switch (location.kind) { diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt new file mode 100644 index 00000000000..54ddb963f94 --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt @@ -0,0 +1,44 @@ +tests/cases/compiler/parameterNamesInTypeParameterList.ts(1,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(5,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(9,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(14,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(17,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(20,22): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/parameterNamesInTypeParameterList.ts (6 errors) ==== + function f0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + class A { + m0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.js b/tests/baselines/reference/parameterNamesInTypeParameterList.js new file mode 100644 index 00000000000..2fbd7fad3cb --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.js @@ -0,0 +1,53 @@ +//// [parameterNamesInTypeParameterList.ts] +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} + +//// [parameterNamesInTypeParameterList.js] +function f0(a) { + a.b; +} +function f1(_a) { + var a = _a.a; + a.b; +} +function f2(_a) { + var a = _a[0]; + a.b; +} +var A = (function () { + function A() { + } + A.prototype.m0 = function (a) { + a.b; + }; + A.prototype.m1 = function (_a) { + var a = _a.a; + a.b; + }; + A.prototype.m2 = function (_a) { + var a = _a[0]; + a.b; + }; + return A; +})(); diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt new file mode 100644 index 00000000000..872a0a10923 --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt @@ -0,0 +1,17 @@ +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,10): error TS2304: Cannot find name 'T'. +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,13): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/typeParametersAndParametersInComputedNames.ts (2 errors) ==== + function foo(a: T) : string { + return ""; + } + + class A { + [foo(a)](a: T) { + ~ +!!! error TS2304: Cannot find name 'T'. + ~ +!!! error TS2304: Cannot find name 'a'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.js b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js new file mode 100644 index 00000000000..1cb53663fbd --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js @@ -0,0 +1,21 @@ +//// [typeParametersAndParametersInComputedNames.ts] +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} + +//// [typeParametersAndParametersInComputedNames.js] +function foo(a) { + return ""; +} +var A = (function () { + function A() { + } + A.prototype[foo(a)] = function (a) { + }; + return A; +})(); diff --git a/tests/cases/compiler/parameterNamesInTypeParameterList.ts b/tests/cases/compiler/parameterNamesInTypeParameterList.ts new file mode 100644 index 00000000000..dba122db866 --- /dev/null +++ b/tests/cases/compiler/parameterNamesInTypeParameterList.ts @@ -0,0 +1,23 @@ +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} \ No newline at end of file diff --git a/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts new file mode 100644 index 00000000000..273dcb2a3ea --- /dev/null +++ b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts @@ -0,0 +1,8 @@ +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} \ No newline at end of file From 9531d929c703dade551c2d0497574b9e8b2f1dff Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Nov 2015 14:34:02 -0800 Subject: [PATCH 88/93] update test with pr feedback --- tests/baselines/reference/typeGuardInClass.js | 8 ++++---- tests/baselines/reference/typeGuardInClass.symbols | 6 ++++-- tests/baselines/reference/typeGuardInClass.types | 10 ++++++---- .../expressions/typeGuards/typeGuardInClass.ts | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/typeGuardInClass.js b/tests/baselines/reference/typeGuardInClass.js index 44bda9f4cb5..0ce25a7c11c 100644 --- a/tests/baselines/reference/typeGuardInClass.js +++ b/tests/baselines/reference/typeGuardInClass.js @@ -4,14 +4,14 @@ let x: string | number; if (typeof x === "string") { let n = class { constructor() { - x; // Should be "string" + let y: string = x; } } } else { let m = class { constructor() { - x; // Should be "number" + let y: number = x; } } } @@ -22,7 +22,7 @@ var x; if (typeof x === "string") { var n = (function () { function class_1() { - x; // Should be "string" + var y = x; } return class_1; })(); @@ -30,7 +30,7 @@ if (typeof x === "string") { else { var m = (function () { function class_2() { - x; // Should be "number" + var y = x; } return class_2; })(); diff --git a/tests/baselines/reference/typeGuardInClass.symbols b/tests/baselines/reference/typeGuardInClass.symbols index 66de1651859..cc0e745e4de 100644 --- a/tests/baselines/reference/typeGuardInClass.symbols +++ b/tests/baselines/reference/typeGuardInClass.symbols @@ -9,7 +9,8 @@ if (typeof x === "string") { >n : Symbol(n, Decl(typeGuardInClass.ts, 3, 7)) constructor() { - x; // Should be "string" + let y: string = x; +>y : Symbol(y, Decl(typeGuardInClass.ts, 5, 15)) >x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) } } @@ -19,7 +20,8 @@ else { >m : Symbol(m, Decl(typeGuardInClass.ts, 10, 7)) constructor() { - x; // Should be "number" + let y: number = x; +>y : Symbol(y, Decl(typeGuardInClass.ts, 12, 15)) >x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) } } diff --git a/tests/baselines/reference/typeGuardInClass.types b/tests/baselines/reference/typeGuardInClass.types index 8552b58508e..93fe9f28c5e 100644 --- a/tests/baselines/reference/typeGuardInClass.types +++ b/tests/baselines/reference/typeGuardInClass.types @@ -10,10 +10,11 @@ if (typeof x === "string") { let n = class { >n : typeof (Anonymous class) ->class { constructor() { x; // Should be "string" } } : typeof (Anonymous class) +>class { constructor() { let y: string = x; } } : typeof (Anonymous class) constructor() { - x; // Should be "string" + let y: string = x; +>y : string >x : string } } @@ -21,10 +22,11 @@ if (typeof x === "string") { else { let m = class { >m : typeof (Anonymous class) ->class { constructor() { x; // Should be "number" } } : typeof (Anonymous class) +>class { constructor() { let y: number = x; } } : typeof (Anonymous class) constructor() { - x; // Should be "number" + let y: number = x; +>y : number >x : number } } diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts index f88088744fc..aa394aaa75b 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts @@ -3,14 +3,14 @@ let x: string | number; if (typeof x === "string") { let n = class { constructor() { - x; // Should be "string" + let y: string = x; } } } else { let m = class { constructor() { - x; // Should be "number" + let y: number = x; } } } From 31039a3fff48b23a40c087e530eaa55f9f092b89 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 17 Nov 2015 15:22:26 -0800 Subject: [PATCH 89/93] disallow references to function locals from return type annotations --- src/compiler/checker.ts | 14 +++++++++----- ...nctionVariableInReturnTypeAnnotation.errors.txt | 10 ++++++++++ .../functionVariableInReturnTypeAnnotation.js | 11 +++++++++++ .../functionVariableInReturnTypeAnnotation.ts | 4 ++++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt create mode 100644 tests/baselines/reference/functionVariableInReturnTypeAnnotation.js create mode 100644 tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f9fd563b873..5348d2b19f0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -492,12 +492,16 @@ namespace ts { : false; } if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { - // function scoped variables are visible only inside function body and parameter list - // technically here we might mix parameters and variables declared in function, - // however this case is detected separately when checking initializers of parameters + // parameters are visible only inside function body, parameter list and return type + // technically for parameter list case here we might mix parameters and variables declared in function, + // however it is detected separately when checking initializers of parameters // to make sure that they reference no variables declared after them. - useResult = lastLocation === (location).type || - lastLocation.kind === SyntaxKind.Parameter; + useResult = + lastLocation.kind === SyntaxKind.Parameter || + ( + lastLocation === (location).type && + result.valueDeclaration.kind === SyntaxKind.Parameter + ); } } diff --git a/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt new file mode 100644 index 00000000000..93a35292b70 --- /dev/null +++ b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts(1,24): error TS2304: Cannot find name 'b'. + + +==== tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts (1 errors) ==== + function bar(): typeof b { + ~ +!!! error TS2304: Cannot find name 'b'. + var b = 1; + return undefined; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js new file mode 100644 index 00000000000..191255e52c2 --- /dev/null +++ b/tests/baselines/reference/functionVariableInReturnTypeAnnotation.js @@ -0,0 +1,11 @@ +//// [functionVariableInReturnTypeAnnotation.ts] +function bar(): typeof b { + var b = 1; + return undefined; +} + +//// [functionVariableInReturnTypeAnnotation.js] +function bar() { + var b = 1; + return undefined; +} diff --git a/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts b/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts new file mode 100644 index 00000000000..c8936034a25 --- /dev/null +++ b/tests/cases/compiler/functionVariableInReturnTypeAnnotation.ts @@ -0,0 +1,4 @@ +function bar(): typeof b { + var b = 1; + return undefined; +} \ No newline at end of file From cf007461b923fa5b826d29daa9ad1d124182d871 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Nov 2015 01:41:41 -0800 Subject: [PATCH 90/93] Fixed invalid code for binding expressions. --- scripts/tslint/preferConstRule.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index e4ffa396fb7..c14264ed7af 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -106,11 +106,23 @@ class PreferConstWalker extends Lint.RuleWalker { 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); + const kind = element.kind; + + if (kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + this.markAssignment((element as ts.ShorthandPropertyAssignment).name); } - else if (isBindingPattern(element.name)) { - this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern); + else if (kind === ts.SyntaxKind.PropertyAssignment) { + const rhs = (element as ts.PropertyAssignment).initializer; + + if (rhs.kind === ts.SyntaxKind.Identifier) { + this.markAssignment(rhs as ts.Identifier); + } + else if (rhs.kind === ts.SyntaxKind.ObjectLiteralExpression || rhs.kind === ts.SyntaxKind.ArrayLiteralExpression) { + this.visitBindingLiteralExpression(rhs as ts.ObjectLiteralExpression | ts.ArrayLiteralExpression); + } + else { + // Should be an error, but do nothing for now. + } } } } From 15d689cdcdddb0b926d3e96249cde6f1abe7105c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Nov 2015 01:46:17 -0800 Subject: [PATCH 91/93] Simplify simplify simplify. --- scripts/tslint/preferConstRule.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index c14264ed7af..a4606481079 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -112,17 +112,10 @@ class PreferConstWalker extends Lint.RuleWalker { this.markAssignment((element as ts.ShorthandPropertyAssignment).name); } else if (kind === ts.SyntaxKind.PropertyAssignment) { - const rhs = (element as ts.PropertyAssignment).initializer; - - if (rhs.kind === ts.SyntaxKind.Identifier) { - this.markAssignment(rhs as ts.Identifier); - } - else if (rhs.kind === ts.SyntaxKind.ObjectLiteralExpression || rhs.kind === ts.SyntaxKind.ArrayLiteralExpression) { - this.visitBindingLiteralExpression(rhs as ts.ObjectLiteralExpression | ts.ArrayLiteralExpression); - } - else { - // Should be an error, but do nothing for now. - } + this.visitLHSExpressions((element as ts.PropertyAssignment).initializer); + } + else { + // Should we throw an exception? } } } From cbb61654fbe95c0d77e7a0ac6c3ba3080ee705c4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Nov 2015 01:52:08 -0800 Subject: [PATCH 92/93] Small refactorings. --- scripts/tslint/preferConstRule.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index a4606481079..2b5b5550c06 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -85,12 +85,12 @@ class PreferConstWalker extends Lint.RuleWalker { visitBinaryExpression(node: ts.BinaryExpression) { if (isAssignmentOperator(node.operatorToken.kind)) { - this.visitLHSExpressions(node.left); + this.visitLeftHandSideExpression(node.left); } super.visitBinaryExpression(node); } - private visitLHSExpressions(node: ts.Expression) { + private visitLeftHandSideExpression(node: ts.Expression) { while (node.kind === ts.SyntaxKind.ParenthesizedExpression) { node = (node as ts.ParenthesizedExpression).expression; } @@ -112,7 +112,7 @@ class PreferConstWalker extends Lint.RuleWalker { this.markAssignment((element as ts.ShorthandPropertyAssignment).name); } else if (kind === ts.SyntaxKind.PropertyAssignment) { - this.visitLHSExpressions((element as ts.PropertyAssignment).initializer); + this.visitLeftHandSideExpression((element as ts.PropertyAssignment).initializer); } else { // Should we throw an exception? @@ -122,7 +122,7 @@ class PreferConstWalker extends Lint.RuleWalker { else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) { const pattern = node as ts.ArrayLiteralExpression; for (const element of pattern.elements) { - this.visitLHSExpressions(element); + this.visitLeftHandSideExpression(element); } } } @@ -150,7 +150,7 @@ class PreferConstWalker extends Lint.RuleWalker { private visitAnyUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) { if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) { - this.visitLHSExpressions(node.operand); + this.visitLeftHandSideExpression(node.operand); } } @@ -216,12 +216,12 @@ class PreferConstWalker extends Lint.RuleWalker { } } - private collectNameIdentifiers(value: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map) { + private collectNameIdentifiers(declaration: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map) { if (node.kind === ts.SyntaxKind.Identifier) { - table[(node as ts.Identifier).text] = {declaration: value, usages: 0}; + table[(node as ts.Identifier).text] = { declaration, usages: 0 }; } else { - this.collectBindingPatternIdentifiers(value, node as ts.BindingPattern, table); + this.collectBindingPatternIdentifiers(declaration, node as ts.BindingPattern, table); } } From bd84b844ff8982ee0c2e8a7f9d777925760fea8a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 18 Nov 2015 10:07:42 -0800 Subject: [PATCH 93/93] Remove unnecessary 'else' block. --- scripts/tslint/preferConstRule.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/tslint/preferConstRule.ts b/scripts/tslint/preferConstRule.ts index 2b5b5550c06..aaa1b0e53d5 100644 --- a/scripts/tslint/preferConstRule.ts +++ b/scripts/tslint/preferConstRule.ts @@ -114,9 +114,6 @@ class PreferConstWalker extends Lint.RuleWalker { else if (kind === ts.SyntaxKind.PropertyAssignment) { this.visitLeftHandSideExpression((element as ts.PropertyAssignment).initializer); } - else { - // Should we throw an exception? - } } } else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {