From 595cb11f22d4bb3fe4bbf3e4d0366c6b5903c57a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Jun 2017 11:01:32 -0700 Subject: [PATCH 001/246] Excess property checks for discriminated unions This uses the same code as #14006, which improves error messages for discriminated unions. --- src/compiler/checker.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 266fbe573beb9..ddfebd84ad69d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8964,6 +8964,13 @@ namespace ts { (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { return false; } + if (target.flags & TypeFlags.Union) { + const discriminantType = findMatchingDiscriminantType(source, target as UnionType); + if (discriminantType) { + // check excess properties against discriminant type only, not the entire union + return hasExcessProperties(source, discriminantType, reportErrors); + } + } for (const prop of getPropertiesOfObjectType(source)) { if (!isKnownProperty(target, prop.name, isComparingJsxAttributes)) { if (reportErrors) { From 8302ebcd8b2f493539abf6fd1d9f9f3718af252c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Jun 2017 11:03:52 -0700 Subject: [PATCH 002/246] Test:excess property checks--discriminated unions --- .../discriminatedUnionErrorMessage.errors.txt | 12 +++---- .../excessPropertyCheckWithUnions.errors.txt | 33 +++++++++++++++++++ .../excessPropertyCheckWithUnions.js | 19 +++++++++++ .../compiler/excessPropertyCheckWithUnions.ts | 12 +++++++ 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt create mode 100644 tests/baselines/reference/excessPropertyCheckWithUnions.js create mode 100644 tests/cases/compiler/excessPropertyCheckWithUnions.ts diff --git a/tests/baselines/reference/discriminatedUnionErrorMessage.errors.txt b/tests/baselines/reference/discriminatedUnionErrorMessage.errors.txt index 6f1eb511d3714..e54727befd0e1 100644 --- a/tests/baselines/reference/discriminatedUnionErrorMessage.errors.txt +++ b/tests/baselines/reference/discriminatedUnionErrorMessage.errors.txt @@ -1,6 +1,5 @@ -tests/cases/compiler/discriminatedUnionErrorMessage.ts(8,5): error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'. - Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'. - Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'. +tests/cases/compiler/discriminatedUnionErrorMessage.ts(10,5): error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'. + Object literal may only specify known properties, and 'x' does not exist in type 'Square'. ==== tests/cases/compiler/discriminatedUnionErrorMessage.ts (1 errors) ==== @@ -12,12 +11,11 @@ tests/cases/compiler/discriminatedUnionErrorMessage.ts(8,5): error TS2322: Type | Rectangle | Circle; let shape: Shape = { - ~~~~~ -!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'. -!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'. -!!! error TS2322: Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'. kind: "sq", x: 12, + ~~~~~ +!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'. +!!! error TS2322: Object literal may only specify known properties, and 'x' does not exist in type 'Square'. y: 13, } \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt new file mode 100644 index 0000000000000..1a01f8cb5b840 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -0,0 +1,33 @@ +tests/cases/compiler/excessPropertyCheckWithUnions.ts(10,30): error TS2322: Type '{ tag: "T"; a1: string; }' is not assignable to type 'ADT'. + Object literal may only specify known properties, and 'a1' does not exist in type '{ tag: "T"; }'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(11,21): error TS2322: Type '{ tag: "A"; d20: 12; }' is not assignable to type 'ADT'. + Object literal may only specify known properties, and 'd20' does not exist in type '{ tag: "A"; a1: string; }'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(12,1): error TS2322: Type '{ tag: "D"; }' is not assignable to type 'ADT'. + Type '{ tag: "D"; }' is not assignable to type '{ tag: "D"; d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; }'. + Property 'd20' is missing in type '{ tag: "D"; }'. + + +==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (3 errors) ==== + type ADT = { + tag: "A", + a1: string + } | { + tag: "D", + d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 + } | { + tag: "T", + } + let wrong: ADT = { tag: "T", a1: "extra" } + ~~~~~~~~~~~ +!!! error TS2322: Type '{ tag: "T"; a1: string; }' is not assignable to type 'ADT'. +!!! error TS2322: Object literal may only specify known properties, and 'a1' does not exist in type '{ tag: "T"; }'. + wrong = { tag: "A", d20: 12 } + ~~~~~~~ +!!! error TS2322: Type '{ tag: "A"; d20: 12; }' is not assignable to type 'ADT'. +!!! error TS2322: Object literal may only specify known properties, and 'd20' does not exist in type '{ tag: "A"; a1: string; }'. + wrong = { tag: "D" } + ~~~~~ +!!! error TS2322: Type '{ tag: "D"; }' is not assignable to type 'ADT'. +!!! error TS2322: Type '{ tag: "D"; }' is not assignable to type '{ tag: "D"; d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; }'. +!!! error TS2322: Property 'd20' is missing in type '{ tag: "D"; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js new file mode 100644 index 0000000000000..79c30bce9c769 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -0,0 +1,19 @@ +//// [excessPropertyCheckWithUnions.ts] +type ADT = { + tag: "A", + a1: string +} | { + tag: "D", + d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 +} | { + tag: "T", +} +let wrong: ADT = { tag: "T", a1: "extra" } +wrong = { tag: "A", d20: 12 } +wrong = { tag: "D" } + + +//// [excessPropertyCheckWithUnions.js] +var wrong = { tag: "T", a1: "extra" }; +wrong = { tag: "A", d20: 12 }; +wrong = { tag: "D" }; diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts new file mode 100644 index 0000000000000..8b1abf1b7640a --- /dev/null +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -0,0 +1,12 @@ +type ADT = { + tag: "A", + a1: string +} | { + tag: "D", + d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 +} | { + tag: "T", +} +let wrong: ADT = { tag: "T", a1: "extra" } +wrong = { tag: "A", d20: 12 } +wrong = { tag: "D" } From c8d856a5d4489860114d809c010a52a56a5f91a7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 9 Jun 2017 09:51:07 -0700 Subject: [PATCH 003/246] Correct excess property error on ambiguous discriminated unions --- src/compiler/checker.ts | 7 ++- .../excessPropertyCheckWithUnions.errors.txt | 58 ++++++++++++++++++- .../excessPropertyCheckWithUnions.js | 41 +++++++++++++ .../compiler/excessPropertyCheckWithUnions.ts | 28 +++++++++ 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ddfebd84ad69d..559d6ae71baf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9029,6 +9029,7 @@ namespace ts { function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { const sourceProperties = getPropertiesOfObjectType(source); + let match: Type; if (sourceProperties) { for (const sourceProperty of sourceProperties) { if (isDiscriminantProperty(target, sourceProperty.name)) { @@ -9036,12 +9037,16 @@ namespace ts { for (const type of target.types) { const targetType = getTypeOfPropertyOfType(type, sourceProperty.name); if (targetType && isRelatedTo(sourceType, targetType)) { - return type; + if (match) { + return undefined; + } + match = type; } } } } } + return match; } function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean): Ternary { diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index 1a01f8cb5b840..9714c90ba619b 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -5,9 +5,21 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(11,21): error TS2322: Type tests/cases/compiler/excessPropertyCheckWithUnions.ts(12,1): error TS2322: Type '{ tag: "D"; }' is not assignable to type 'ADT'. Type '{ tag: "D"; }' is not assignable to type '{ tag: "D"; d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; }'. Property 'd20' is missing in type '{ tag: "D"; }'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(33,28): error TS2322: Type '{ tag: "A"; x: string; extra: number; }' is not assignable to type 'Ambiguous'. + Object literal may only specify known properties, and 'extra' does not exist in type 'Ambiguous'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(34,26): error TS2322: Type '{ tag: "A"; y: number; extra: number; }' is not assignable to type 'Ambiguous'. + Object literal may only specify known properties, and 'extra' does not exist in type 'Ambiguous'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(39,1): error TS2322: Type '{ tag: "A"; }' is not assignable to type 'Ambiguous'. + Type '{ tag: "A"; }' is not assignable to type '{ tag: "C"; }'. + Types of property 'tag' are incompatible. + Type '"A"' is not assignable to type '"C"'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type 'Ambiguous'. + Type '{ tag: "A"; z: true; }' is not assignable to type '{ tag: "C"; }'. + Types of property 'tag' are incompatible. + Type '"A"' is not assignable to type '"C"'. -==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (3 errors) ==== +==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (7 errors) ==== type ADT = { tag: "A", a1: string @@ -30,4 +42,48 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(12,1): error TS2322: Type !!! error TS2322: Type '{ tag: "D"; }' is not assignable to type 'ADT'. !!! error TS2322: Type '{ tag: "D"; }' is not assignable to type '{ tag: "D"; d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; }'. !!! error TS2322: Property 'd20' is missing in type '{ tag: "D"; }'. + + type Ambiguous = { + tag: "A", + x: string + } | { + tag: "A", + y: number + } | { + tag: "B", + z: boolean + } | { + tag: "C" + } + let amb: Ambiguous + // no error for ambiguous tag, even when it could satisfy both constituents at once + amb = { tag: "A", x: "hi" } + amb = { tag: "A", y: 12 } + amb = { tag: "A", x: "hi", y: 12 } + + // correctly error on excess property 'extra', even when ambiguous + amb = { tag: "A", x: "hi", extra: 12 } + ~~~~~~~~~ +!!! error TS2322: Type '{ tag: "A"; x: string; extra: number; }' is not assignable to type 'Ambiguous'. +!!! error TS2322: Object literal may only specify known properties, and 'extra' does not exist in type 'Ambiguous'. + amb = { tag: "A", y: 12, extra: 12 } + ~~~~~~~~~ +!!! error TS2322: Type '{ tag: "A"; y: number; extra: number; }' is not assignable to type 'Ambiguous'. +!!! error TS2322: Object literal may only specify known properties, and 'extra' does not exist in type 'Ambiguous'. + + // assignability errors still work. + // But note that the error for `z: true` is the fallback one of reporting on + // the last constituent since assignability error reporting can't find a single best discriminant either. + amb = { tag: "A" } + ~~~ +!!! error TS2322: Type '{ tag: "A"; }' is not assignable to type 'Ambiguous'. +!!! error TS2322: Type '{ tag: "A"; }' is not assignable to type '{ tag: "C"; }'. +!!! error TS2322: Types of property 'tag' are incompatible. +!!! error TS2322: Type '"A"' is not assignable to type '"C"'. + amb = { tag: "A", z: true } + ~~~ +!!! error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type 'Ambiguous'. +!!! error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type '{ tag: "C"; }'. +!!! error TS2322: Types of property 'tag' are incompatible. +!!! error TS2322: Type '"A"' is not assignable to type '"C"'. \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js index 79c30bce9c769..fb0a5a6f81911 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.js +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -11,9 +11,50 @@ type ADT = { let wrong: ADT = { tag: "T", a1: "extra" } wrong = { tag: "A", d20: 12 } wrong = { tag: "D" } + +type Ambiguous = { + tag: "A", + x: string +} | { + tag: "A", + y: number +} | { + tag: "B", + z: boolean +} | { + tag: "C" +} +let amb: Ambiguous +// no error for ambiguous tag, even when it could satisfy both constituents at once +amb = { tag: "A", x: "hi" } +amb = { tag: "A", y: 12 } +amb = { tag: "A", x: "hi", y: 12 } + +// correctly error on excess property 'extra', even when ambiguous +amb = { tag: "A", x: "hi", extra: 12 } +amb = { tag: "A", y: 12, extra: 12 } + +// assignability errors still work. +// But note that the error for `z: true` is the fallback one of reporting on +// the last constituent since assignability error reporting can't find a single best discriminant either. +amb = { tag: "A" } +amb = { tag: "A", z: true } //// [excessPropertyCheckWithUnions.js] var wrong = { tag: "T", a1: "extra" }; wrong = { tag: "A", d20: 12 }; wrong = { tag: "D" }; +var amb; +// no error for ambiguous tag, even when it could satisfy both constituents at once +amb = { tag: "A", x: "hi" }; +amb = { tag: "A", y: 12 }; +amb = { tag: "A", x: "hi", y: 12 }; +// correctly error on excess property 'extra', even when ambiguous +amb = { tag: "A", x: "hi", extra: 12 }; +amb = { tag: "A", y: 12, extra: 12 }; +// assignability errors still work. +// But note that the error for `z: true` is the fallback one of reporting on +// the last constituent since assignability error reporting can't find a single best discriminant either. +amb = { tag: "A" }; +amb = { tag: "A", z: true }; diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts index 8b1abf1b7640a..51f36d137fdda 100644 --- a/tests/cases/compiler/excessPropertyCheckWithUnions.ts +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -10,3 +10,31 @@ type ADT = { let wrong: ADT = { tag: "T", a1: "extra" } wrong = { tag: "A", d20: 12 } wrong = { tag: "D" } + +type Ambiguous = { + tag: "A", + x: string +} | { + tag: "A", + y: number +} | { + tag: "B", + z: boolean +} | { + tag: "C" +} +let amb: Ambiguous +// no error for ambiguous tag, even when it could satisfy both constituents at once +amb = { tag: "A", x: "hi" } +amb = { tag: "A", y: 12 } +amb = { tag: "A", x: "hi", y: 12 } + +// correctly error on excess property 'extra', even when ambiguous +amb = { tag: "A", x: "hi", extra: 12 } +amb = { tag: "A", y: 12, extra: 12 } + +// assignability errors still work. +// But note that the error for `z: true` is the fallback one of reporting on +// the last constituent since assignability error reporting can't find a single best discriminant either. +amb = { tag: "A" } +amb = { tag: "A", z: true } From d04f4a93a7fff465eaf2da93931f1949f6e49a22 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 9 Jun 2017 15:42:14 -0700 Subject: [PATCH 004/246] Do not check excess properties for multi-discriminant unions --- src/compiler/checker.ts | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 559d6ae71baf1..f79e74746d453 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9028,20 +9028,19 @@ namespace ts { } function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { - const sourceProperties = getPropertiesOfObjectType(source); let match: Type; + const sourceProperties = getPropertiesOfObjectType(source); if (sourceProperties) { - for (const sourceProperty of sourceProperties) { - if (isDiscriminantProperty(target, sourceProperty.name)) { - const sourceType = getTypeOfSymbol(sourceProperty); - for (const type of target.types) { - const targetType = getTypeOfPropertyOfType(type, sourceProperty.name); - if (targetType && isRelatedTo(sourceType, targetType)) { - if (match) { - return undefined; - } - match = type; + const sourceProperty = findSingleDiscriminantProperty(sourceProperties, target); + if (sourceProperty) { + const sourceType = getTypeOfSymbol(sourceProperty); + for (const type of target.types) { + const targetType = getTypeOfPropertyOfType(type, sourceProperty.name); + if (targetType && isRelatedTo(sourceType, targetType)) { + if (match) { + return undefined; } + match = type; } } } @@ -10839,6 +10838,19 @@ namespace ts { return false; } + function findSingleDiscriminantProperty(sourceProperties: Symbol[], target: Type): Symbol | undefined { + let result: Symbol; + for (const sourceProperty of sourceProperties) { + if (isDiscriminantProperty(target, sourceProperty.name)) { + if (result) { + return undefined; + } + result = sourceProperty; + } + } + return result; + } + function isOrContainsMatchingReference(source: Node, target: Node) { return isMatchingReference(source, target) || containsMatchingReference(source, target); } From 8a7186d1901197e9d050b1a200470c1cd1a065c5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 9 Jun 2017 15:47:57 -0700 Subject: [PATCH 005/246] Add more excess property check tests for unions --- .../excessPropertyCheckWithUnions.errors.txt | 10 ++++++++++ .../reference/excessPropertyCheckWithUnions.js | 14 ++++++++++++++ .../compiler/excessPropertyCheckWithUnions.ts | 10 ++++++++++ 3 files changed, 34 insertions(+) diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index 9714c90ba619b..3b7e5a787d2aa 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -86,4 +86,14 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type !!! error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type '{ tag: "C"; }'. !!! error TS2322: Types of property 'tag' are incompatible. !!! error TS2322: Type '"A"' is not assignable to type '"C"'. + + type Overlapping = + | { a: 1, b: 1, first: string } + | { a: 2, second: string } + | { b: 3, third: string } + let over: Overlapping + + // these two are not reported because there are two discriminant properties + over = { a: 1, b: 1, first: "ok", second: "error" } + over = { a: 1, b: 1, first: "ok", third: "error" } \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js index fb0a5a6f81911..c6da660b52dde 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.js +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -39,6 +39,16 @@ amb = { tag: "A", y: 12, extra: 12 } // the last constituent since assignability error reporting can't find a single best discriminant either. amb = { tag: "A" } amb = { tag: "A", z: true } + +type Overlapping = + | { a: 1, b: 1, first: string } + | { a: 2, second: string } + | { b: 3, third: string } +let over: Overlapping + +// these two are not reported because there are two discriminant properties +over = { a: 1, b: 1, first: "ok", second: "error" } +over = { a: 1, b: 1, first: "ok", third: "error" } //// [excessPropertyCheckWithUnions.js] @@ -58,3 +68,7 @@ amb = { tag: "A", y: 12, extra: 12 }; // the last constituent since assignability error reporting can't find a single best discriminant either. amb = { tag: "A" }; amb = { tag: "A", z: true }; +var over; +// these two are not reported because there are two discriminant properties +over = { a: 1, b: 1, first: "ok", second: "error" }; +over = { a: 1, b: 1, first: "ok", third: "error" }; diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts index 51f36d137fdda..9a7968fe5114e 100644 --- a/tests/cases/compiler/excessPropertyCheckWithUnions.ts +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -38,3 +38,13 @@ amb = { tag: "A", y: 12, extra: 12 } // the last constituent since assignability error reporting can't find a single best discriminant either. amb = { tag: "A" } amb = { tag: "A", z: true } + +type Overlapping = + | { a: 1, b: 1, first: string } + | { a: 2, second: string } + | { b: 3, third: string } +let over: Overlapping + +// these two are not reported because there are two discriminant properties +over = { a: 1, b: 1, first: "ok", second: "error" } +over = { a: 1, b: 1, first: "ok", third: "error" } From 4de96abd8fc5d678d6b494a953d3127dd2acf871 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 16 Jun 2017 14:37:39 -0700 Subject: [PATCH 006/246] Use the same logic of getting current directory as the one used when emitting files through project It means we would use currentDirectory as project Root or script info's directory as the current directory Fixes issue reported in https://developercommunity.visualstudio.com/content/problem/57099/typescript-generated-source-maps-have-invalid-path.html --- src/compiler/program.ts | 12 +++---- src/compiler/types.ts | 6 +++- src/harness/unittests/compileOnSave.ts | 45 +++++++++++++++++++++++++- src/server/builder.ts | 4 +-- src/server/project.ts | 11 ++++++- src/services/services.ts | 4 +-- src/services/transpile.ts | 2 +- src/services/types.ts | 2 +- 8 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bbc0fa0978090..30c61f50dff2f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -874,12 +874,12 @@ namespace ts { return oldProgram.structureIsReused = StructureIsReused.Completely; } - function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { + function getEmitHost(writeFileCallback?: WriteFileCallback, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitHost { return { getCanonicalFileName, getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, - getCurrentDirectory: () => currentDirectory, + getCurrentDirectory: getCurrentDirectoryCallback || (() => currentDirectory), getNewLine: () => host.getNewLine(), getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, @@ -907,15 +907,15 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } - function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers): EmitResult { - return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers)); + function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult { + return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, getCurrentDirectoryCallback)); } function isEmitBlocked(emitFileName: string): boolean { return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName)); } - function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { + function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult { let declarationDiagnostics: Diagnostic[] = []; if (options.noEmit) { @@ -960,7 +960,7 @@ namespace ts { const transformers = emitOnlyDtsFiles ? [] : getTransformers(options, customTransformers); const emitResult = emitFiles( emitResolver, - getEmitHost(writeFileCallback), + getEmitHost(writeFileCallback, getCurrentDirectoryCallback), sourceFile, emitOnlyDtsFiles, transformers); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ac64624e1a6aa..ac5de15322697 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2405,6 +2405,10 @@ namespace ts { (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void; } + export interface GetCurrentDirectoryCallback { + (): string; + } + export class OperationCanceledException { } export interface CancellationToken { @@ -2436,7 +2440,7 @@ namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 7e262a1b2573d..3183ffd71b064 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -600,5 +600,48 @@ namespace ts.projectSystem { assert.isTrue(outFileContent.indexOf(file2.content) === -1); assert.isTrue(outFileContent.indexOf(file3.content) === -1); }); + + it("should use project root as current directory so that compile on save results in correct file mapping", () => { + const inputFileName = "Foo.ts"; + const file1 = { + path: `/root/TypeScriptProject3/TypeScriptProject3/${inputFileName}`, + content: "consonle.log('file1');" + }; + const externalProjectName = "/root/TypeScriptProject3/TypeScriptProject3/TypeScriptProject3.csproj"; + const host = createServerHost([file1, libFile]); + const session = createSession(host); + const projectService = session.getProjectService(); + + const outFileName = "bar.js"; + projectService.openExternalProject({ + rootFiles: toExternalFiles([file1.path]), + options: { + outFile: outFileName, + sourceMap: true, + compileOnSave: true + }, + projectFileName: externalProjectName + }); + + const emitRequest = makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path }); + session.executeCommand(emitRequest); + + // Verify js file + const expectedOutFileName = "/root/TypeScriptProject3/TypeScriptProject3/" + outFileName; + assert.isTrue(host.fileExists(expectedOutFileName)); + const outFileContent = host.readFile(expectedOutFileName); + verifyContentHasString(outFileContent, file1.content); + verifyContentHasString(outFileContent, `//# sourceMappingURL=${outFileName}.map`); + + // Verify map file + const expectedMapFileName = expectedOutFileName + ".map"; + assert.isTrue(host.fileExists(expectedMapFileName)); + const mapFileContent = host.readFile(expectedMapFileName); + verifyContentHasString(mapFileContent, `"sources":["${inputFileName}"]`); + + function verifyContentHasString(content: string, string: string) { + assert.isTrue(content.indexOf(string) !== -1, `Expected "${content}" to have "${string}"`); + } + }); }); -} \ No newline at end of file +} diff --git a/src/server/builder.ts b/src/server/builder.ts index 895732ebeceb2..711045d0ae630 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -148,9 +148,9 @@ namespace ts.server { const { emitSkipped, outputFiles } = this.project.getFileEmitOutput(fileInfo.scriptInfo, /*emitOnlyDtsFiles*/ false); if (!emitSkipped) { - const projectRootPath = this.project.getProjectRootPath(); + const currentDirectoryForEmit = this.project.getCurrentDirectoryForScriptInfoEmit(scriptInfo); for (const outputFile of outputFiles) { - const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, projectRootPath ? projectRootPath : getDirectoryPath(scriptInfo.fileName)); + const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, currentDirectoryForEmit); writeFile(outputFileAbsoluteFileName, outputFile.text, outputFile.writeByteOrderMark); } } diff --git a/src/server/project.ts b/src/server/project.ts index ac040a77ace24..a7d8605315b06 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -367,7 +367,16 @@ namespace ts.server { if (!this.languageServiceEnabled) { return undefined; } - return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles); + + const getCurrentDirectoryCallback = memoize( + () => this.getCurrentDirectoryForScriptInfoEmit(info) + ); + return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles, getCurrentDirectoryCallback); + } + + getCurrentDirectoryForScriptInfoEmit(info: ScriptInfo) { + const projectRootPath = this.getProjectRootPath(); + return projectRootPath || getDirectoryPath(info.fileName); } getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean) { diff --git a/src/services/services.ts b/src/services/services.ts index b508285b182fb..11061181ee63c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1528,7 +1528,7 @@ namespace ts { return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput { + function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitOutput { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1543,7 +1543,7 @@ namespace ts { } const customTransformers = host.getCustomTransformers && host.getCustomTransformers(); - const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, getCurrentDirectoryCallback); return { outputFiles, diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 561c188c6cdf4..5ba393a90c946 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -104,7 +104,7 @@ namespace ts { addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); + program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers, /*getCurrentDirectoryCallback*/ undefined); Debug.assert(outputText !== undefined, "Output generation failed"); diff --git a/src/services/types.ts b/src/services/types.ts index 2d47da2fd1d08..07aaaeeb4b47c 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -269,7 +269,7 @@ namespace ts { getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; + getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, getCurrentDirectoryCallBack?: GetCurrentDirectoryCallback): EmitOutput; getProgram(): Program; From 0bd3d8c2eb01a0e881177c59e1f3a9136533de05 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 15:03:20 -0700 Subject: [PATCH 007/246] unspoof call expression start in iife --- src/services/formatting/smartIndenter.ts | 53 ++++++++++++++++-------- src/services/services.ts | 2 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 5 ++- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 18b0479c85a30..7609296ccf554 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -9,18 +9,21 @@ namespace ts.formatting { } /** - * Computed indentation for a given position in source file - * @param position - position in file - * @param sourceFile - target source file - * @param options - set of editor options that control indentation - * @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file. - * true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e. + * @param assumeNewLineBeforeCloseBrace + * `false` when called on text from a real source file. + * `true` when we need to assume `position` is on a newline. + * + * This is useful for codefixes. Consider + * ``` * function f() { * |} - * when inserting some text after open brace we would like to get the value of indentation as if newline was already there. - * However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior, + * ``` + * with `position` at `|`. + * + * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior, */ - export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } @@ -136,8 +139,10 @@ namespace ts.formatting { let parent: Node = current.parent; let parentStart: LineAndCharacter; - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' + // Walk up the tree and collect indentation for pairs of parent-child nodes. + // indentation is not added if + // * parent and child nodes start on the same line + // * parent is IfStatement and child starts on the same line with 'else clause' while (parent) { let useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -174,22 +179,24 @@ namespace ts.formatting { indentationDelta += options.indentSize; } + // Update current and parent. + + const callExpressionUsesTrueStart = + isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + current = parent; - currentStart = parentStart; parent = current.parent; + currentStart = callExpressionUsesTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; + parentStart = undefined; } return indentationDelta + getBaseIndentation(options); } - function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); - if (containingList) { - return sourceFile.getLineAndCharacterOfPosition(containingList.pos); - } - - return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); + const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); + return sourceFile.getLineAndCharacterOfPosition(startPos); } /* @@ -268,6 +275,16 @@ namespace ts.formatting { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } + export function isParameterAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (!(isCallExpression(parent) && contains(parent.arguments, child))) { + return false; + } + + const callExpressionEnd = parent.expression.getEnd(); + const expressionEndLine = getLineAndCharacterOfPosition(sourceFile, callExpressionEnd).line; + return expressionEndLine === childStartLine; + } + export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) { const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile); diff --git a/src/services/services.ts b/src/services/services.ts index b508285b182fb..13e6e2a2e4b64 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1742,7 +1742,7 @@ namespace ts { start = timestamp(); - const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); + const result = formatting.SmartIndenter.getIndentationAtPosition(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 5aa4ebca7d088..e0d96d26a5570 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -465,7 +465,7 @@ namespace ts.textChanges { change.options.indentation !== undefined ? change.options.indentation : change.useIndentationFromFile - ? formatting.SmartIndenter.getIndentation(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) + ? formatting.SmartIndenter.getIndentationAtPosition(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) : 0; const delta = change.options.delta !== undefined diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 78c7140373631..f0a0c3ee758a4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -402,8 +402,11 @@ namespace ts { return start < end; } + /** + * Assumes `candidate.start <= position` holds. + */ export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean { - return candidate.end > position || !isCompletedNode(candidate, sourceFile); + return position < candidate.end || !isCompletedNode(candidate, sourceFile); } export function isCompletedNode(n: Node, sourceFile: SourceFile): boolean { From d1423739cdaea03f1e27f9522816e52517581dbe Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 15:05:15 -0700 Subject: [PATCH 008/246] add test --- tests/cases/fourslash/indentationInAmdIife.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/cases/fourslash/indentationInAmdIife.ts diff --git a/tests/cases/fourslash/indentationInAmdIife.ts b/tests/cases/fourslash/indentationInAmdIife.ts new file mode 100644 index 0000000000000..461693344634b --- /dev/null +++ b/tests/cases/fourslash/indentationInAmdIife.ts @@ -0,0 +1,52 @@ +/// + +//// function foo(a?,b?) { b(a); } +//// +//// (foo)(1, function() {/*4_0*/ +//// }); +//// +//// ///////////// +//// +//// ( +//// foo)(1, function () {/*4_1*/ +//// }); +//// (foo) +//// (1, function () {/*8_0*/ +//// }); +//// (foo)(1, +//// function () {/*8_1*/ +//// }); +//// (foo)(1, function() +//// {/*4_2*/ +//// }); +//// +//// ////////////////////// +//// +//// (foo +//// )(1, function () {/*4_3*/ +//// }); +//// (foo +//// ) +//// (1, function () {/*8_2*/ +//// }); +//// (foo +//// )(1, +//// function () {/*8_3*/ +//// }); +//// (foo +//// )(1, function() +//// {/*4_4*/ +//// }); + + +for (let i = 0; i < 5; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} + +for (let i = 1; i < 4; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} \ No newline at end of file From 902d0f501803af9d6e24ffe6ca85751386efd6ba Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 17:04:39 -0700 Subject: [PATCH 009/246] cleanup --- src/services/formatting/smartIndenter.ts | 22 +++++++++---------- tests/cases/fourslash/indentationInAmdIife.ts | 13 +++++------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 7609296ccf554..e1e440a95059a 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -21,7 +21,7 @@ namespace ts.formatting { * with `position` at `|`. * * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. - * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior, + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { @@ -139,10 +139,9 @@ namespace ts.formatting { let parent: Node = current.parent; let parentStart: LineAndCharacter; - // Walk up the tree and collect indentation for pairs of parent-child nodes. - // indentation is not added if - // * parent and child nodes start on the same line - // * parent is IfStatement and child starts on the same line with 'else clause' + // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if + // * parent and child nodes start on the same line, or + // * parent is an IfStatement and child starts on the same line as an 'else clause'. while (parent) { let useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -157,6 +156,7 @@ namespace ts.formatting { return actualIndentation + indentationDelta; } } + parentStart = getParentStart(parent, current, sourceFile); const parentAndChildShareLine = parentStart.line === currentStart.line || @@ -179,14 +179,14 @@ namespace ts.formatting { indentationDelta += options.indentSize; } - // Update current and parent. + // Update `current` and `parent`. - const callExpressionUsesTrueStart = + const useTrueStart = isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; - currentStart = callExpressionUsesTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; + currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; parentStart = undefined; } @@ -280,9 +280,9 @@ namespace ts.formatting { return false; } - const callExpressionEnd = parent.expression.getEnd(); - const expressionEndLine = getLineAndCharacterOfPosition(sourceFile, callExpressionEnd).line; - return expressionEndLine === childStartLine; + const expressionOfCallExpressionEnd = parent.expression.getEnd(); + const expressionOfCallExpressionEndLine = getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; + return expressionOfCallExpressionEndLine === childStartLine; } export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { diff --git a/tests/cases/fourslash/indentationInAmdIife.ts b/tests/cases/fourslash/indentationInAmdIife.ts index 461693344634b..f735ae57eb219 100644 --- a/tests/cases/fourslash/indentationInAmdIife.ts +++ b/tests/cases/fourslash/indentationInAmdIife.ts @@ -5,11 +5,8 @@ //// (foo)(1, function() {/*4_0*/ //// }); //// -//// ///////////// +//// // No line-breaks in the expression part of the call expression //// -//// ( -//// foo)(1, function () {/*4_1*/ -//// }); //// (foo) //// (1, function () {/*8_0*/ //// }); @@ -20,8 +17,11 @@ //// {/*4_2*/ //// }); //// -//// ////////////////////// -//// +//// // Contains line-breaks in the expression part of the call expression. +//// +//// ( +//// foo)(1, function () {/*4_1*/ +//// }); //// (foo //// )(1, function () {/*4_3*/ //// }); @@ -38,7 +38,6 @@ //// {/*4_4*/ //// }); - for (let i = 0; i < 5; ++i) { goTo.marker(`4_${i}`); edit.insertLine(""); From 1251668342775f00c5f2654490e6078289eb35af Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 22 Jun 2017 10:32:04 -0700 Subject: [PATCH 010/246] rename variables --- src/services/formatting/smartIndenter.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index e1e440a95059a..7900f8bb8c331 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -137,7 +137,7 @@ namespace ts.formatting { options: EditorSettings): number { let parent: Node = current.parent; - let parentStart: LineAndCharacter; + let containingListOrParentStart: LineAndCharacter; // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if // * parent and child nodes start on the same line, or @@ -157,9 +157,9 @@ namespace ts.formatting { } } - parentStart = getParentStart(parent, current, sourceFile); + containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile); const parentAndChildShareLine = - parentStart.line === currentStart.line || + containingListOrParentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { @@ -182,18 +182,18 @@ namespace ts.formatting { // Update `current` and `parent`. const useTrueStart = - isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; - currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; - parentStart = undefined; + currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : containingListOrParentStart; + containingListOrParentStart = undefined; } return indentationDelta + getBaseIndentation(options); } - function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { + function getContainingListOrParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); return sourceFile.getLineAndCharacterOfPosition(startPos); @@ -275,7 +275,7 @@ namespace ts.formatting { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - export function isParameterAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { if (!(isCallExpression(parent) && contains(parent.arguments, child))) { return false; } From ad62037f25cf09092a08aef21b2791f751f63a35 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 15 Aug 2017 11:42:25 -0700 Subject: [PATCH 011/246] Use checkExpression to resolve symbols --- src/compiler/checker.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1c41be84ba741..cfa76c0315a9f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16376,9 +16376,7 @@ namespace ts { // in a JS file // Note:JS inferred classes might come from a variable declaration instead of a function declaration. // In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration. - let funcSymbol = node.expression.kind === SyntaxKind.Identifier ? - getResolvedSymbol(node.expression as Identifier) : - checkExpression(node.expression).symbol; + let funcSymbol = checkExpression(node.expression).symbol; if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) { funcSymbol = getSymbolOfNode((funcSymbol.valueDeclaration).initializer); } From 17994588b22f2e2f853f02e70ee9716135866f58 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 15 Aug 2017 11:58:57 -0700 Subject: [PATCH 012/246] Actual fix + test --- src/compiler/checker.ts | 3 +++ .../fourslash/indirectClassInstantiation.ts | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/cases/fourslash/indirectClassInstantiation.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cfa76c0315a9f..aa03332af2d30 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16377,6 +16377,9 @@ namespace ts { // Note:JS inferred classes might come from a variable declaration instead of a function declaration. // In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration. let funcSymbol = checkExpression(node.expression).symbol; + if (!funcSymbol && node.expression.kind === SyntaxKind.Identifier) { + funcSymbol = getResolvedSymbol(node.expression as Identifier); + } if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) { funcSymbol = getSymbolOfNode((funcSymbol.valueDeclaration).initializer); } diff --git a/tests/cases/fourslash/indirectClassInstantiation.ts b/tests/cases/fourslash/indirectClassInstantiation.ts new file mode 100644 index 0000000000000..c4d0d38d6ed94 --- /dev/null +++ b/tests/cases/fourslash/indirectClassInstantiation.ts @@ -0,0 +1,21 @@ +/// + +// @allowJs: true +// @Filename: something.js +//// function TestObj(){ +//// this.property = "value"; +//// } +//// var constructor = TestObj; +//// var instance = new constructor(); +//// instance./*a*/ +//// var class2 = function() { }; +//// class2.prototype.blah = function() { }; +//// var inst2 = new class2(); +//// inst2.blah/*b*/; + +goTo.marker('a'); +verify.completionListContains('property'); +edit.backspace(); + +goTo.marker('b'); +verify.quickInfoIs('(property) class2.blah: () => void'); From 262d7bd53bda077786341c9cd3ad912d0f4f5eb0 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 16:23:45 -0700 Subject: [PATCH 013/246] revert method rename --- src/services/formatting/smartIndenter.ts | 2 +- src/services/services.ts | 2 +- src/services/textChanges.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index b04369f30ae3e..fac61be45d554 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -23,7 +23,7 @@ namespace ts.formatting { * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ - export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } diff --git a/src/services/services.ts b/src/services/services.ts index 4008d4382fc6a..90f9acd82eab3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1772,7 +1772,7 @@ namespace ts { start = timestamp(); - const result = formatting.SmartIndenter.getIndentationAtPosition(position, sourceFile, settings); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 8883724f6988f..b4a2d3e07e226 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -557,7 +557,7 @@ namespace ts.textChanges { options.indentation !== undefined ? options.indentation : (options.useIndentationFromFile !== false) - ? formatting.SmartIndenter.getIndentationAtPosition(pos, sourceFile, formatOptions, posStartsLine || (options.prefix === this.newLineCharacter)) + ? formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, posStartsLine || (options.prefix === this.newLineCharacter)) : 0; const delta = options.delta !== undefined From e3a720f863fc353b6ec8c77aee5470cd1011a3d8 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 16:25:06 -0700 Subject: [PATCH 014/246] explain changes and remove spurious assignment --- src/services/formatting/smartIndenter.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index fac61be45d554..7701cff182c3b 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -202,7 +202,14 @@ namespace ts.formatting { indentationDelta += options.indentSize; } - // Update `current` and `parent`. + // In our AST, a call argument's `parent` is the call-expression, not the argument list. + // We would like to increase indentation based on the relationship between an argument and its argument-list, + // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list. + // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression + // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation. + // + // Instead, when at an argument, we unspoof the starting position of the enclosing call expression + // *after* applying indentation for the argument. const useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); @@ -210,7 +217,6 @@ namespace ts.formatting { current = parent; parent = current.parent; currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : containingListOrParentStart; - containingListOrParentStart = undefined; } return indentationDelta + getBaseIndentation(options); From 4b464ebca887d5bdf69968c8f46c7c888c97be59 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 17:56:34 -0700 Subject: [PATCH 015/246] add tests * verified that new tests show no regressions against master --- tests/cases/fourslash/indentationInArrays.ts | 21 +++++++++++ .../fourslash/indentationInAssignment.ts | 37 +++++++++++++++++++ .../indentationInAsyncExpressions.ts | 16 ++++++++ .../fourslash/indentationInClassExpression.ts | 31 ++++++++++++++++ tests/cases/fourslash/indentationInObject.ts | 30 +++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 tests/cases/fourslash/indentationInArrays.ts create mode 100644 tests/cases/fourslash/indentationInAssignment.ts create mode 100644 tests/cases/fourslash/indentationInAsyncExpressions.ts create mode 100644 tests/cases/fourslash/indentationInClassExpression.ts create mode 100644 tests/cases/fourslash/indentationInObject.ts diff --git a/tests/cases/fourslash/indentationInArrays.ts b/tests/cases/fourslash/indentationInArrays.ts new file mode 100644 index 0000000000000..9468ff43a0870 --- /dev/null +++ b/tests/cases/fourslash/indentationInArrays.ts @@ -0,0 +1,21 @@ +/// + +//// function foo() { +//// [/*8_0*/1,2,3]; +//// [1/*8_1*/,2,3]; +//// [1,/*8_2*/2,3]; +//// [ +//// 1,/*8_3*/2,3]; +//// [1,2,3/*8_4*/]; +//// [ +//// 1,2,3/*8_5*/]; +//// [1,2,3]/*8_6*/; +//// [ +//// 1,2,3]/*8_7*/; +//// } + +for (let i = 0; i < 8; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} diff --git a/tests/cases/fourslash/indentationInAssignment.ts b/tests/cases/fourslash/indentationInAssignment.ts new file mode 100644 index 0000000000000..253cb30cf381b --- /dev/null +++ b/tests/cases/fourslash/indentationInAssignment.ts @@ -0,0 +1,37 @@ +/// + +//// var v0 = /*4_0*/ +//// 1; +//// +//// let v1 = 1 /*4_1*/ +//// + 10; +//// +//// let v2 = 1 + /*4_2*/ +//// 1; +//// +//// let v3 = 1 + (function /*0_0*/(x: number, y: number) { return x || y; })(0, 1); +//// +//// let v4 = 1 + (function (x: number, /*4_3*/y: number) { return x || y; })(0, 1); +//// +//// let v5 = 1 + (function (x: number, y: number) { /*4_4*/return x || y; })(0, 1); +//// +//// let v6 = 1 + (function (x: number, y: number) { return x || y;/*0_1*/})(0, 1); +//// +//// let v7 = 1 + (function (x: number, y: number) { +//// return x || y;/*4_5*/ +//// })(0, 1); +//// +//// let v8 = 1 + (function (x: number, y: number) { return x || y; })(0, /*4_6*/1); + + +for (let i = 0; i < 2; ++i) { + goTo.marker(`0_${i}`); + edit.insertLine(""); + verify.indentationIs(0); +} + +for (let i = 0; i < 7; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInAsyncExpressions.ts b/tests/cases/fourslash/indentationInAsyncExpressions.ts new file mode 100644 index 0000000000000..5273dcbd97a89 --- /dev/null +++ b/tests/cases/fourslash/indentationInAsyncExpressions.ts @@ -0,0 +1,16 @@ +/// + + +//// async function* foo() { +//// yield /*8_0*/await 1; +//// yield await /*8_1*/1; +//// yield +//// await /*8_2*/1; +//// yield await 1/*8_3*/; +//// } + +for (let i = 0; i < 4; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInClassExpression.ts b/tests/cases/fourslash/indentationInClassExpression.ts new file mode 100644 index 0000000000000..77ac668790a5b --- /dev/null +++ b/tests/cases/fourslash/indentationInClassExpression.ts @@ -0,0 +1,31 @@ +/// + +////function foo() { +//// let x: any; +//// x = /*8_0*/class { constructor(public x: number) { } }; +//// x = class /*4_0*/{ constructor(public x: number) { } }; +//// x = class { /*8_1*/constructor(public x: number) { } }; +//// x = class { constructor(/*12_0*/public x: number) { } }; +//// x = class { constructor(public /*12_1*/x: number) { } }; +//// x = class { constructor(public x: number) {/*8_2*/ } }; +//// x = class { +//// constructor(/*12_2*/public x: number) { } +//// }; +//// x = class { +//// constructor(public x: number) {/*8_3*/ } +//// }; +//// x = class { +//// constructor(public x: number) { }/*4_1*/}; +////} + +function verifyIndentation(level: number, count: number) { + for (let i = 0; i < count; ++i) { + goTo.marker(`${level}_${i}`); + edit.insertLine(""); + verify.indentationIs(level); + } +} + +verifyIndentation(4, 2); +verifyIndentation(8, 4); +verifyIndentation(12, 3); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInObject.ts b/tests/cases/fourslash/indentationInObject.ts new file mode 100644 index 0000000000000..2acb651c933c8 --- /dev/null +++ b/tests/cases/fourslash/indentationInObject.ts @@ -0,0 +1,30 @@ +/// + +//// function foo() { +//// {/*8_0*/x:1;y:2;z:3}; +//// {x:1/*12_0*/;y:2;z:3}; +//// {x:1;/*8_1*/y:2;z:3}; +//// { +//// x:1;/*8_2*/y:2;z:3}; +//// {x:1;y:2;z:3/*4_0*/}; +//// { +//// x:1;y:2;z:3/*4_1*/}; +//// {x:1;y:2;z:3}/*4_2*/; +//// { +//// x:1;y:2;z:3}/*4_3*/; +//// } + +for (let i = 0; i < 4; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} +for (let i = 0; i < 3; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} + + goTo.marker(`12_0`); + edit.insertLine(""); + verify.indentationIs(12); From cc8770390c8419a14d8563407a368a6f63eb3aef Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 20 Sep 2017 10:23:45 -0700 Subject: [PATCH 016/246] remove newline --- src/services/textChanges.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index b4a2d3e07e226..f3ad7df16076e 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -553,7 +553,6 @@ namespace ts.textChanges { const posStartsLine = getLineStartPositionForPosition(pos, sourceFile) === pos; const initialIndentation = - options.indentation !== undefined ? options.indentation : (options.useIndentationFromFile !== false) From db78d5a5875becd3859aa414263c9ca6f91aabc2 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 21 Sep 2017 16:53:38 -0700 Subject: [PATCH 017/246] add error message test --- src/harness/unittests/session.ts | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 18109cfa9db26..58d8c1b66d8f0 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -386,6 +386,61 @@ namespace ts.server { }); }); + describe("exceptions", () => { + const command = "testhandler"; + class TestSession extends Session { + lastSent: protocol.Message; + private exceptionRaisingHandler(_request: protocol.Request): { response?: any, responseRequired: boolean } { + f1(); + return; + function f1() { + throw new Error("myMessage"); + } + } + + constructor() { + super({ + host: mockHost, + cancellationToken: nullCancellationToken, + useSingleInferredProject: false, + useInferredProjectPerProjectRoot: false, + typingsInstaller: undefined, + byteLength: Utils.byteLength, + hrtime: process.hrtime, + logger: projectSystem.nullLogger, + canUseEvents: true + }); + this.addProtocolHandler(command, this.exceptionRaisingHandler); + } + send(msg: protocol.Message) { + this.lastSent = msg; + } + } + + it("raised in a protocol handler generate an event", () => { + + const session = new TestSession(); + + const request = { + command, + seq: 0, + type: "request" + }; + + session.onMessage(JSON.stringify(request)); + const lastSent = session.lastSent as protocol.Response; + + expect(lastSent).to.contain({ + seq: 0, + type: "response", + command, + success: false + }); + + expect(lastSent.message).has.string("myMessage").and.has.string("f1"); + }); + }); + describe("how Session is extendable via subclassing", () => { class TestSession extends Session { lastSent: protocol.Message; From b21c46b9b56d1d8cf7a6ebe71dd26f43015fc552 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 22 Sep 2017 16:21:31 -0700 Subject: [PATCH 018/246] support @extends in jsdoc --- src/compiler/checker.ts | 4 +- src/compiler/parser.ts | 12 +- src/compiler/types.ts | 11 +- src/compiler/utilities.ts | 8 +- src/services/completions.ts | 4 +- tests/baselines/reference/APISample_jsdoc.js | 4 +- tests/cases/compiler/APISample_jsdoc.ts | 232 +++++++++---------- tests/cases/fourslash/jsDocAugments.ts | 3 +- tests/cases/fourslash/jsDocExtends.ts | 22 ++ 9 files changed, 164 insertions(+), 136 deletions(-) create mode 100644 tests/cases/fourslash/jsDocExtends.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5c835582da023..2dbfa6bd40995 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4986,10 +4986,10 @@ namespace ts { baseType = getReturnTypeOfSignature(constructors[0]); } - // In a JS file, you can use the @augments jsdoc tag to specify a base type with type parameters + // In a JS file, you can use the @augments and @extends jsdoc tags to specify a base type with type parameters const valueDecl = type.symbol.valueDeclaration; if (valueDecl && isInJavaScriptFile(valueDecl)) { - const augTag = getJSDocAugmentsTag(type.symbol.valueDeclaration); + const augTag = getJSDocAugmentsOrExtendsTag(type.symbol.valueDeclaration); if (augTag) { baseType = getTypeFromTypeNode(augTag.typeExpression.type); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 3809a07142139..7e9ac8c580478 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -423,8 +423,9 @@ namespace ts { return visitNode(cbNode, (node).typeExpression); case SyntaxKind.JSDocTypeTag: return visitNode(cbNode, (node).typeExpression); - case SyntaxKind.JSDocAugmentsTag: - return visitNode(cbNode, (node).typeExpression); + case SyntaxKind.JSDocAugmentsOrExtendsTag: + case SyntaxKind.JSDocExtendsTag: + return visitNode(cbNode, (node).typeExpression); case SyntaxKind.JSDocTemplateTag: return visitNodes(cbNode, cbNodes, (node).typeParameters); case SyntaxKind.JSDocTypedefTag: @@ -6366,7 +6367,8 @@ namespace ts { if (tagName) { switch (tagName.escapedText) { case "augments": - tag = parseAugmentsTag(atToken, tagName); + case "extends": + tag = parseAugmentsOrExtendsTag(atToken, tagName); break; case "class": case "constructor": @@ -6603,10 +6605,10 @@ namespace ts { return finishNode(result); } - function parseAugmentsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsTag { + function parseAugmentsOrExtendsTag(atToken: AtToken, tagName: Identifier): JSDocAugmentsOrExtendsTag { const typeExpression = tryParseTypeExpression(); - const result = createNode(SyntaxKind.JSDocAugmentsTag, atToken.pos); + const result = createNode(SyntaxKind.JSDocAugmentsOrExtendsTag, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.typeExpression = typeExpression; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4e5ca9f07e77f..e8f5423679801 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -363,7 +363,8 @@ namespace ts { JSDocVariadicType, JSDocComment, JSDocTag, - JSDocAugmentsTag, + JSDocAugmentsOrExtendsTag, + JSDocExtendsTag, JSDocClassTag, JSDocParameterTag, JSDocReturnTag, @@ -2159,8 +2160,12 @@ namespace ts { kind: SyntaxKind.JSDocTag; } - export interface JSDocAugmentsTag extends JSDocTag { - kind: SyntaxKind.JSDocAugmentsTag; + /** + * Note that `@extends` is a synonym of `@augments`. + * Both are covered by this interface. + */ + export interface JSDocAugmentsOrExtendsTag extends JSDocTag { + kind: SyntaxKind.JSDocAugmentsOrExtendsTag; typeExpression: JSDocTypeExpression; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 674215b05835e..f9a0c4c38ab3d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4072,8 +4072,8 @@ namespace ts { } /** Gets the JSDoc augments tag for the node if present */ - export function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined { - return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag; + export function getJSDocAugmentsOrExtendsTag(node: Node): JSDocAugmentsOrExtendsTag | undefined { + return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsOrExtendsTag) as JSDocAugmentsOrExtendsTag; } /** Gets the JSDoc class tag for the node if present */ @@ -4765,8 +4765,8 @@ namespace ts { return node.kind === SyntaxKind.JSDocComment; } - export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { - return node.kind === SyntaxKind.JSDocAugmentsTag; + export function isJSDocAugmentsOrExtendsTag(node: Node): node is JSDocAugmentsOrExtendsTag { + return node.kind === SyntaxKind.JSDocAugmentsOrExtendsTag; } export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { diff --git a/src/services/completions.ts b/src/services/completions.ts index e271ef1210405..a954f687cb5d8 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -581,11 +581,11 @@ namespace ts.Completions { return { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, keywordFilters }; - type JSDocTagWithTypeExpression = JSDocAugmentsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; + type JSDocTagWithTypeExpression = JSDocAugmentsOrExtendsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; function isTagWithTypeExpression(tag: JSDocTag): tag is JSDocTagWithTypeExpression { switch (tag.kind) { - case SyntaxKind.JSDocAugmentsTag: + case SyntaxKind.JSDocAugmentsOrExtendsTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocPropertyTag: case SyntaxKind.JSDocReturnTag: diff --git a/tests/baselines/reference/APISample_jsdoc.js b/tests/baselines/reference/APISample_jsdoc.js index c74e188f38b22..33857d06a6a66 100644 --- a/tests/baselines/reference/APISample_jsdoc.js +++ b/tests/baselines/reference/APISample_jsdoc.js @@ -101,7 +101,7 @@ function getAllTags(node: ts.Node) { function getSomeOtherTags(node: ts.Node) { const tags: (ts.JSDocTag | undefined)[] = []; - tags.push(ts.getJSDocAugmentsTag(node)); + tags.push(ts.getJSDocAugmentsOrExtendsTag(node)); tags.push(ts.getJSDocClassTag(node)); tags.push(ts.getJSDocReturnTag(node)); const type = ts.getJSDocTypeTag(node); @@ -200,7 +200,7 @@ function getAllTags(node) { } function getSomeOtherTags(node) { var tags = []; - tags.push(ts.getJSDocAugmentsTag(node)); + tags.push(ts.getJSDocAugmentsOrExtendsTag(node)); tags.push(ts.getJSDocClassTag(node)); tags.push(ts.getJSDocReturnTag(node)); var type = ts.getJSDocTypeTag(node); diff --git a/tests/cases/compiler/APISample_jsdoc.ts b/tests/cases/compiler/APISample_jsdoc.ts index 70b814ffff487..491ff2b7a20d0 100644 --- a/tests/cases/compiler/APISample_jsdoc.ts +++ b/tests/cases/compiler/APISample_jsdoc.ts @@ -1,116 +1,116 @@ -// @module: commonjs -// @includebuiltfile: typescript_standalone.d.ts -// @strict:true - -/* - * Note: This test is a public API sample. The original sources can be found - * at: https://github.com/YousefED/typescript-json-schema - * https://github.com/vega/ts-json-schema-generator - * Please log a "breaking change" issue for any API breaking change affecting this issue - */ - -declare var console: any; - -import * as ts from "typescript"; - -// excerpted from https://github.com/YousefED/typescript-json-schema -// (converted from a method and modified; for example, `this: any` to compensate, among other changes) -function parseCommentsIntoDefinition(this: any, - symbol: ts.Symbol, - definition: {description?: string, [s: string]: string | undefined}, - otherAnnotations: { [s: string]: true}): void { - if (!symbol) { - return; - } - - // the comments for a symbol - let comments = symbol.getDocumentationComment(); - - if (comments.length) { - definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join(""); - } - - // jsdocs are separate from comments - const jsdocs = symbol.getJsDocTags(); - jsdocs.forEach(doc => { - // if we have @TJS-... annotations, we have to parse them - const { name, text } = doc; - if (this.userValidationKeywords[name]) { - definition[name] = this.parseValue(text); - } else { - // special annotations - otherAnnotations[doc.name] = true; - } - }); -} - - -// excerpted from https://github.com/vega/ts-json-schema-generator -export interface Annotations { - [name: string]: any; -} -function getAnnotations(this: any, node: ts.Node): Annotations | undefined { - const symbol: ts.Symbol = (node as any).symbol; - if (!symbol) { - return undefined; - } - - const jsDocTags: ts.JSDocTagInfo[] = symbol.getJsDocTags(); - if (!jsDocTags || !jsDocTags.length) { - return undefined; - } - - const annotations: Annotations = jsDocTags.reduce((result: Annotations, jsDocTag: ts.JSDocTagInfo) => { - const value = this.parseJsDocTag(jsDocTag); - if (value !== undefined) { - result[jsDocTag.name] = value; - } - - return result; - }, {}); - return Object.keys(annotations).length ? annotations : undefined; -} - -// these examples are artificial and mostly nonsensical -function parseSpecificTags(node: ts.Node) { - if (node.kind === ts.SyntaxKind.Parameter) { - return ts.getJSDocParameterTags(node as ts.ParameterDeclaration); - } - if (node.kind === ts.SyntaxKind.FunctionDeclaration) { - const func = node as ts.FunctionDeclaration; - if (ts.hasJSDocParameterTags(func)) { - const flat: ts.JSDocTag[] = []; - for (const tags of func.parameters.map(ts.getJSDocParameterTags)) { - if (tags) flat.push(...tags); - } - return flat; - } - } -} - -function getReturnTypeFromJSDoc(node: ts.Node) { - if (node.kind === ts.SyntaxKind.FunctionDeclaration) { - return ts.getJSDocReturnType(node); - } - let type = ts.getJSDocType(node); - if (type && type.kind === ts.SyntaxKind.FunctionType) { - return (type as ts.FunctionTypeNode).type; - } -} - -function getAllTags(node: ts.Node) { - ts.getJSDocTags(node); -} - -function getSomeOtherTags(node: ts.Node) { - const tags: (ts.JSDocTag | undefined)[] = []; - tags.push(ts.getJSDocAugmentsTag(node)); - tags.push(ts.getJSDocClassTag(node)); - tags.push(ts.getJSDocReturnTag(node)); - const type = ts.getJSDocTypeTag(node); - if (type) { - tags.push(type); - } - tags.push(ts.getJSDocTemplateTag(node)); - return tags; -} +// @module: commonjs +// @includebuiltfile: typescript_standalone.d.ts +// @strict:true + +/* + * Note: This test is a public API sample. The original sources can be found + * at: https://github.com/YousefED/typescript-json-schema + * https://github.com/vega/ts-json-schema-generator + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var console: any; + +import * as ts from "typescript"; + +// excerpted from https://github.com/YousefED/typescript-json-schema +// (converted from a method and modified; for example, `this: any` to compensate, among other changes) +function parseCommentsIntoDefinition(this: any, + symbol: ts.Symbol, + definition: {description?: string, [s: string]: string | undefined}, + otherAnnotations: { [s: string]: true}): void { + if (!symbol) { + return; + } + + // the comments for a symbol + let comments = symbol.getDocumentationComment(); + + if (comments.length) { + definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join(""); + } + + // jsdocs are separate from comments + const jsdocs = symbol.getJsDocTags(); + jsdocs.forEach(doc => { + // if we have @TJS-... annotations, we have to parse them + const { name, text } = doc; + if (this.userValidationKeywords[name]) { + definition[name] = this.parseValue(text); + } else { + // special annotations + otherAnnotations[doc.name] = true; + } + }); +} + + +// excerpted from https://github.com/vega/ts-json-schema-generator +export interface Annotations { + [name: string]: any; +} +function getAnnotations(this: any, node: ts.Node): Annotations | undefined { + const symbol: ts.Symbol = (node as any).symbol; + if (!symbol) { + return undefined; + } + + const jsDocTags: ts.JSDocTagInfo[] = symbol.getJsDocTags(); + if (!jsDocTags || !jsDocTags.length) { + return undefined; + } + + const annotations: Annotations = jsDocTags.reduce((result: Annotations, jsDocTag: ts.JSDocTagInfo) => { + const value = this.parseJsDocTag(jsDocTag); + if (value !== undefined) { + result[jsDocTag.name] = value; + } + + return result; + }, {}); + return Object.keys(annotations).length ? annotations : undefined; +} + +// these examples are artificial and mostly nonsensical +function parseSpecificTags(node: ts.Node) { + if (node.kind === ts.SyntaxKind.Parameter) { + return ts.getJSDocParameterTags(node as ts.ParameterDeclaration); + } + if (node.kind === ts.SyntaxKind.FunctionDeclaration) { + const func = node as ts.FunctionDeclaration; + if (ts.hasJSDocParameterTags(func)) { + const flat: ts.JSDocTag[] = []; + for (const tags of func.parameters.map(ts.getJSDocParameterTags)) { + if (tags) flat.push(...tags); + } + return flat; + } + } +} + +function getReturnTypeFromJSDoc(node: ts.Node) { + if (node.kind === ts.SyntaxKind.FunctionDeclaration) { + return ts.getJSDocReturnType(node); + } + let type = ts.getJSDocType(node); + if (type && type.kind === ts.SyntaxKind.FunctionType) { + return (type as ts.FunctionTypeNode).type; + } +} + +function getAllTags(node: ts.Node) { + ts.getJSDocTags(node); +} + +function getSomeOtherTags(node: ts.Node) { + const tags: (ts.JSDocTag | undefined)[] = []; + tags.push(ts.getJSDocAugmentsOrExtendsTag(node)); + tags.push(ts.getJSDocClassTag(node)); + tags.push(ts.getJSDocReturnTag(node)); + const type = ts.getJSDocTypeTag(node); + if (type) { + tags.push(type); + } + tags.push(ts.getJSDocTemplateTag(node)); + return tags; +} diff --git a/tests/cases/fourslash/jsDocAugments.ts b/tests/cases/fourslash/jsDocAugments.ts index 24458c529fb92..cd2190e548683 100644 --- a/tests/cases/fourslash/jsDocAugments.ts +++ b/tests/cases/fourslash/jsDocAugments.ts @@ -15,9 +15,8 @@ // @Filename: declarations.d.ts //// declare class Thing { -//// mine: T; +//// mine: T; //// } goTo.marker(); verify.quickInfoIs("(local var) x: string"); - diff --git a/tests/cases/fourslash/jsDocExtends.ts b/tests/cases/fourslash/jsDocExtends.ts new file mode 100644 index 0000000000000..6bce55695333a --- /dev/null +++ b/tests/cases/fourslash/jsDocExtends.ts @@ -0,0 +1,22 @@ +/// + +// @allowJs: true +// @Filename: dummy.js + +//// /** +//// * @extends {Thing} +//// */ +//// class MyStringThing extends Thing { +//// constructor() { +//// var x = this.mine; +//// x/**/; +//// } +//// } + +// @Filename: declarations.d.ts +//// declare class Thing { +//// mine: T; +//// } + +goTo.marker(); +verify.quickInfoIs("(local var) x: string"); From 6d218e2a48ac9ed05a843707a08f4a44851721f1 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 25 Sep 2017 08:56:51 -0700 Subject: [PATCH 019/246] Refactor JSDoc types to Typescript types When the caret is on a Typescript declaration that has no type, but does have a JSDoc annotation with a type, this refactor will add the Typescript equivalent of the JSDoc type. Notes: 1. This doesn't delete the JSDoc comment or delete parts of it. In fact, due to bugs in trivia handling, it sometimes duplicates the comment. These bugs are tracked in #18626. 2. As a bonus, when `noImplicitAny: true`, this shows up as a code fix in VS Code whenever there is a no-implicit-any error. With `noImplicityAny: false`, this code must be invoked via the refactoring command. --- src/compiler/diagnosticMessages.json | 4 + src/compiler/emitter.ts | 46 +++++- src/compiler/utilities.ts | 9 +- src/services/refactors/convertJSDocToTypes.ts | 137 ++++++++++++++++++ src/services/refactors/refactors.ts | 1 + 5 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 src/services/refactors/convertJSDocToTypes.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 662e87d3159af..b3741af80e84f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3703,5 +3703,9 @@ "Extract to {0}": { "category": "Message", "code": 95004 + }, + "Convert to Typescript type": { + "category": "Message", + "code": 95005 } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d458e7e5ef5df..80b08c60d343f 100755 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -545,6 +545,7 @@ namespace ts { case SyntaxKind.TypeReference: return emitTypeReference(node); case SyntaxKind.FunctionType: + case SyntaxKind.JSDocFunctionType: return emitFunctionType(node); case SyntaxKind.ConstructorType: return emitConstructorType(node); @@ -574,6 +575,18 @@ namespace ts { return emitMappedType(node); case SyntaxKind.LiteralType: return emitLiteralType(node); + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + write("any"); + break; + case SyntaxKind.JSDocNullableType: + return emitJSDocNullableType(node as JSDocNullableType); + case SyntaxKind.JSDocNonNullableType: + return emitJSDocNonNullableType(node as JSDocNonNullableType); + case SyntaxKind.JSDocOptionalType: + return emitJSDocOptionalType(node as JSDocOptionalType); + case SyntaxKind.JSDocVariadicType: + return emitJSDocVariadicType(node as JSDocVariadicType); // Binding patterns case SyntaxKind.ObjectBindingPattern: @@ -914,7 +927,15 @@ namespace ts { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emitIfPresent(node.dotDotDotToken); - emit(node.name); + if (node.name) { + emit(node.name); + } + else if (node.parent.kind === SyntaxKind.JSDocFunctionType) { + const i = (node.parent as JSDocFunctionType).parameters.indexOf(node); + if (i > -1) { + write("arg" + i); + } + } emitIfPresent(node.questionToken); emitWithPrefix(": ", node.type); emitExpressionWithPrefix(" = ", node.initializer); @@ -1035,6 +1056,20 @@ namespace ts { emit(node.type); } + function emitJSDocNullableType(node: JSDocNullableType) { + emit(node.type); + write(" | null"); + } + + function emitJSDocNonNullableType(node: JSDocNonNullableType) { + emit(node.type); + } + + function emitJSDocOptionalType(node: JSDocOptionalType) { + emit(node.type); + write(" | undefined"); + } + function emitConstructorType(node: ConstructorTypeNode) { write("new "); emitTypeParameters(node, node.typeParameters); @@ -1060,6 +1095,11 @@ namespace ts { write("[]"); } + function emitJSDocVariadicType(node: JSDocVariadicType) { + emit(node.type); + write("[]"); + } + function emitTupleType(node: TupleTypeNode) { write("["); emitList(node, node.elementTypes, ListFormat.TupleTypeElements); @@ -2357,7 +2397,7 @@ namespace ts { emitList(parentNode, parameters, ListFormat.Parameters); } - function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType, parameters: NodeArray) { const parameter = singleOrUndefined(parameters); return parameter && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter @@ -2374,7 +2414,7 @@ namespace ts { && isIdentifier(parameter.name); // parameter name must be identifier } - function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType, parameters: NodeArray) { if (canEmitSimpleArrowHead(parentNode, parameters)) { emitList(parentNode, parameters, ListFormat.Parameters & ~ListFormat.Parenthesis); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cc7002ca0590c..2fee52f1e3fe3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5034,7 +5034,14 @@ namespace ts { || kind === SyntaxKind.UndefinedKeyword || kind === SyntaxKind.NullKeyword || kind === SyntaxKind.NeverKeyword - || kind === SyntaxKind.ExpressionWithTypeArguments; + || kind === SyntaxKind.ExpressionWithTypeArguments + || kind === SyntaxKind.JSDocAllType + || kind === SyntaxKind.JSDocUnknownType + || kind === SyntaxKind.JSDocNullableType + || kind === SyntaxKind.JSDocNonNullableType + || kind === SyntaxKind.JSDocOptionalType + || kind === SyntaxKind.JSDocFunctionType + || kind === SyntaxKind.JSDocVariadicType; } /** diff --git a/src/services/refactors/convertJSDocToTypes.ts b/src/services/refactors/convertJSDocToTypes.ts new file mode 100644 index 0000000000000..562c26bf50fc8 --- /dev/null +++ b/src/services/refactors/convertJSDocToTypes.ts @@ -0,0 +1,137 @@ +/* @internal */ +namespace ts.refactor.convertJSDocToTypes { + const actionName = "convert"; + + const convertJSDocToTypes: Refactor = { + name: "Convert to Typescript type", + description: Diagnostics.Convert_to_Typescript_type.message, + getEditsForAction, + getAvailableActions + }; + + type DeclarationWithType = + | FunctionLikeDeclaration + | VariableDeclaration + | ParameterDeclaration + | PropertySignature + | PropertyDeclaration; + + registerRefactor(convertJSDocToTypes); + + function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { + if (isInJavaScriptFile(context.file)) { + return undefined; + } + + const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); + const decl = findAncestor(node, isTypedNode); + if (decl && (getJSDocType(decl) || getJSDocReturnType(decl)) && !decl.type) { + return [ + { + name: convertJSDocToTypes.name, + description: convertJSDocToTypes.description, + actions: [ + { + description: convertJSDocToTypes.description, + name: actionName + } + ] + } + ]; + } + } + + function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined { + // Somehow wrong action got invoked? + if (actionName !== action) { + Debug.fail(`actionName !== action: ${actionName} !== ${action}`); + return undefined; + } + + const start = context.startPosition; + const sourceFile = context.file; + const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); + const decl = findAncestor(token, isTypedNode); + const jsdocType = getJSDocType(decl); + const jsdocReturn = getJSDocReturnType(decl); + if (!decl || !jsdocType && !jsdocReturn || decl.type) { + Debug.fail(`!decl || !jsdocType && !jsdocReturn || decl.type: !${decl} || !${jsdocType} && !{jsdocReturn} || ${decl.type}`); + return undefined; + } + + const changeTracker = textChanges.ChangeTracker.fromContext(context); + if (isParameterOfSimpleArrowFunction(decl)) { + // `x => x` becomes `(x: number) => x`, but in order to make the changeTracker generate the parentheses, + // we have to replace the entire function; it doesn't check that the node it's replacing might require + // other syntax changes + const arrow = decl.parent as ArrowFunction; + const param = decl as ParameterDeclaration; + const replacementParam = createParameter(param.decorators, param.modifiers, param.dotDotDotToken, param.name, param.questionToken, jsdocType, param.initializer); + const replacement = createArrowFunction(arrow.modifiers, arrow.typeParameters, [replacementParam], arrow.type, arrow.equalsGreaterThanToken, arrow.body); + changeTracker.replaceRange(sourceFile, { pos: arrow.getStart(), end: arrow.end }, replacement); + } + else { + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, replaceType(decl, jsdocType, jsdocReturn)); + } + return { + edits: changeTracker.getChanges(), + renameFilename: undefined, + renameLocation: undefined + }; + } + + function isTypedNode(node: Node): node is DeclarationWithType { + return isFunctionLikeDeclaration(node) || + node.kind === SyntaxKind.VariableDeclaration || + node.kind === SyntaxKind.Parameter || + node.kind === SyntaxKind.PropertySignature || + node.kind === SyntaxKind.PropertyDeclaration; + } + + function replaceType(decl: DeclarationWithType, jsdocType: TypeNode, jsdocReturn: TypeNode) { + switch (decl.kind) { + case SyntaxKind.VariableDeclaration: + return createVariableDeclaration(decl.name, jsdocType, decl.initializer); + case SyntaxKind.Parameter: + return createParameter(decl.decorators, decl.modifiers, decl.dotDotDotToken, decl.name, decl.questionToken, jsdocType, decl.initializer); + case SyntaxKind.PropertySignature: + return createPropertySignature(decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); + case SyntaxKind.PropertyDeclaration: + return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); + case SyntaxKind.FunctionDeclaration: + return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + case SyntaxKind.FunctionExpression: + return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + case SyntaxKind.ArrowFunction: + return createArrowFunction(decl.modifiers, decl.typeParameters, decl.parameters, jsdocReturn, decl.equalsGreaterThanToken, decl.body); + case SyntaxKind.MethodDeclaration: + return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + case SyntaxKind.GetAccessor: + return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, jsdocReturn, decl.body); + default: + Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`); + return undefined; + } + } + + function isParameterOfSimpleArrowFunction(decl: DeclarationWithType) { + return decl.kind === SyntaxKind.Parameter && decl.parent.kind === SyntaxKind.ArrowFunction && isSimpleArrowFunction(decl.parent); + } + + function isSimpleArrowFunction(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType) { + const parameter = singleOrUndefined(parentNode.parameters); + return parameter + && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter + && !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation + && !some(parentNode.decorators) // parent may not have decorators + && !some(parentNode.modifiers) // parent may not have modifiers + && !some(parentNode.typeParameters) // parent may not have type parameters + && !some(parameter.decorators) // parameter may not have decorators + && !some(parameter.modifiers) // parameter may not have modifiers + && !parameter.dotDotDotToken // parameter may not be rest + && !parameter.questionToken // parameter may not be optional + && !parameter.type // parameter may not have a type annotation + && !parameter.initializer // parameter may not have an initializer + && isIdentifier(parameter.name); // parameter name must be identifier + } +} diff --git a/src/services/refactors/refactors.ts b/src/services/refactors/refactors.ts index 3a33ccc83c2b8..d1d50cb50f9d0 100644 --- a/src/services/refactors/refactors.ts +++ b/src/services/refactors/refactors.ts @@ -1,2 +1,3 @@ +/// /// /// From 8996d11096d3c1de718883de97991b1a41fd3f70 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 25 Sep 2017 09:02:42 -0700 Subject: [PATCH 020/246] Test:refactor JSDoc types to Typescript types --- tests/cases/fourslash/convertJSDocToTypes1.ts | 10 ++ .../cases/fourslash/convertJSDocToTypes10.ts | 15 +++ .../cases/fourslash/convertJSDocToTypes11.ts | 15 +++ .../cases/fourslash/convertJSDocToTypes12.ts | 21 ++++ .../cases/fourslash/convertJSDocToTypes13.ts | 11 ++ tests/cases/fourslash/convertJSDocToTypes2.ts | 6 + tests/cases/fourslash/convertJSDocToTypes3.ts | 54 ++++++++ tests/cases/fourslash/convertJSDocToTypes4.ts | 115 ++++++++++++++++++ tests/cases/fourslash/convertJSDocToTypes5.ts | 15 +++ tests/cases/fourslash/convertJSDocToTypes6.ts | 15 +++ tests/cases/fourslash/convertJSDocToTypes7.ts | 17 +++ tests/cases/fourslash/convertJSDocToTypes8.ts | 17 +++ tests/cases/fourslash/convertJSDocToTypes9.ts | 15 +++ 13 files changed, 326 insertions(+) create mode 100644 tests/cases/fourslash/convertJSDocToTypes1.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes10.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes11.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes12.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes13.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes2.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes3.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes4.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes5.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes6.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes7.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes8.ts create mode 100644 tests/cases/fourslash/convertJSDocToTypes9.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes1.ts b/tests/cases/fourslash/convertJSDocToTypes1.ts new file mode 100644 index 0000000000000..7f90febaca112 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes1.ts @@ -0,0 +1,10 @@ +/// + +// @Filename: test123.ts +/////** @type {number} */ +////var /*1*/x; + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** @type {number} */ +var x: number;`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes10.ts b/tests/cases/fourslash/convertJSDocToTypes10.ts new file mode 100644 index 0000000000000..1e925db81e0c3 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes10.ts @@ -0,0 +1,15 @@ +/// + +/////** +//// * @param {?} x +//// * @returns {number} +//// */ +////var f = /*1*/(/*2*/x) => x + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {?} x + * @returns {number} + */ +var f = (x): number => x`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes11.ts b/tests/cases/fourslash/convertJSDocToTypes11.ts new file mode 100644 index 0000000000000..0315e506dc12f --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes11.ts @@ -0,0 +1,15 @@ +/// + +/////** +//// * @param {?} x +//// * @returns {number} +//// */ +////var f = /*1*/(/*2*/x) => x + +verify.applicableRefactorAvailableAtMarker('2'); +verify.fileAfterApplyingRefactorAtMarker('2', +`/** + * @param {?} x + * @returns {number} + */ +var f = (x: any) => x`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes12.ts b/tests/cases/fourslash/convertJSDocToTypes12.ts new file mode 100644 index 0000000000000..5015cb825d8da --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes12.ts @@ -0,0 +1,21 @@ +/// + +////class C { +//// /** +//// * @return {...*} +//// */ +//// /*1*/m(x) { +//// } +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`class C { + /** + * @return {...*} + */ + /** + * @return {...*} + */ + m(x): any[] { + } +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes13.ts b/tests/cases/fourslash/convertJSDocToTypes13.ts new file mode 100644 index 0000000000000..4ee58da1caa3e --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes13.ts @@ -0,0 +1,11 @@ +/// +////class C { +//// /** @return {number} */ +//// get /*1*/c() { return 12 } +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`class C { + /** @return {number} */ + get c(): number { return 12; } +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes2.ts b/tests/cases/fourslash/convertJSDocToTypes2.ts new file mode 100644 index 0000000000000..85f28de4a9973 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes2.ts @@ -0,0 +1,6 @@ +/// + +// @Filename: test123.ts +/////** @type {number} */ +////var /*1*/x: string; +verify.not.applicableRefactorAvailableAtMarker('1'); diff --git a/tests/cases/fourslash/convertJSDocToTypes3.ts b/tests/cases/fourslash/convertJSDocToTypes3.ts new file mode 100644 index 0000000000000..3d3c1d35f449c --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes3.ts @@ -0,0 +1,54 @@ +/// +/////** +//// * @param {number} x - the first parameter +//// * @param {{ a: string, b: Date }} y - the most complex parameter +//// * @param z - the best parameter +//// * @param alpha - the other best parameter +//// * @param {*} beta - I have no idea how this got here +//// */ +////function f(/*1*/x, /*2*/y, /*3*/z: string, /*4*/alpha, /*5*/beta) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {number} x - the first parameter + * @param {{ a: string, b: Date }} y - the most complex parameter + * @param z - the best parameter + * @param alpha - the other best parameter + * @param {*} beta - I have no idea how this got here + */ +function f(x: number, y, z: string, alpha, beta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.applicableRefactorAvailableAtMarker('2'); +verify.fileAfterApplyingRefactorAtMarker('2', +`/** + * @param {number} x - the first parameter + * @param {{ a: string, b: Date }} y - the most complex parameter + * @param z - the best parameter + * @param alpha - the other best parameter + * @param {*} beta - I have no idea how this got here + */ +function f(x: number, y: { + a: string; + b: Date; +}, z: string, alpha, beta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.not.applicableRefactorAvailableAtMarker('3'); +verify.not.applicableRefactorAvailableAtMarker('4'); +verify.applicableRefactorAvailableAtMarker('5'); +verify.fileAfterApplyingRefactorAtMarker('5', +`/** + * @param {number} x - the first parameter + * @param {{ a: string, b: Date }} y - the most complex parameter + * @param z - the best parameter + * @param alpha - the other best parameter + * @param {*} beta - I have no idea how this got here + */ +function f(x: number, y: { + a: string; + b: Date; +}, z: string, alpha, beta: any) { +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes4.ts b/tests/cases/fourslash/convertJSDocToTypes4.ts new file mode 100644 index 0000000000000..ea80bf0452dd8 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes4.ts @@ -0,0 +1,115 @@ +/// +// @strict: true +/////** +//// * @param {*} x +//// * @param {?} y +//// * @param {number=} z +//// * @param {...number} alpha +//// * @param {function(this:{ a: string}, string, number): boolean} beta +//// * @param {number?} gamma +//// * @param {number!} delta +//// */ +////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y, z, alpha, beta, gamma, delta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.applicableRefactorAvailableAtMarker('2'); +verify.fileAfterApplyingRefactorAtMarker('2', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z, alpha, beta, gamma, delta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.applicableRefactorAvailableAtMarker('3'); +verify.fileAfterApplyingRefactorAtMarker('3', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z: number | undefined, alpha, beta, gamma, delta) { +}`, 'Convert to Typescript type', 'convert'); +verify.applicableRefactorAvailableAtMarker('4'); +verify.fileAfterApplyingRefactorAtMarker('4', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z: number | undefined, alpha: number[], beta, gamma, delta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.applicableRefactorAvailableAtMarker('5'); +verify.fileAfterApplyingRefactorAtMarker('5', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { + a: string; +}, arg1: string, arg2: number) => boolean, gamma, delta) { +}`, 'Convert to Typescript type', 'convert'); +verify.applicableRefactorAvailableAtMarker('6'); +verify.fileAfterApplyingRefactorAtMarker('6', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { + a: string; +}, arg1: string, arg2: number) => boolean, gamma: number | null, delta) { +}`, 'Convert to Typescript type', 'convert'); + +verify.applicableRefactorAvailableAtMarker('7'); +verify.fileAfterApplyingRefactorAtMarker('7', +`/** + * @param {*} x + * @param {?} y + * @param {number=} z + * @param {...number} alpha + * @param {function(this:{ a: string}, string, number): boolean} beta + * @param {number?} gamma + * @param {number!} delta + */ +function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { + a: string; +}, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes5.ts b/tests/cases/fourslash/convertJSDocToTypes5.ts new file mode 100644 index 0000000000000..7647e7be2f8cc --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes5.ts @@ -0,0 +1,15 @@ +/// + +////class C { +//// /** @type {number | null} */ +//// /*1*/p = null +////} + +// NOTE: The duplicated comment is unintentional but needs a serious fix in trivia handling +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`class C { + /** @type {number | null} */ + /** @type {number | null} */ + p: number | null = null; +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes6.ts b/tests/cases/fourslash/convertJSDocToTypes6.ts new file mode 100644 index 0000000000000..991e84b76b648 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes6.ts @@ -0,0 +1,15 @@ +/// + +////declare class C { +//// /** @type {number | null} */ +//// /*1*/p; +////} + +// NOTE: The duplicated comment is unintentional but needs a serious fix in trivia handling +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`declare class C { + /** @type {number | null} */ + /** @type {number | null} */ + p: number | null; +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes7.ts b/tests/cases/fourslash/convertJSDocToTypes7.ts new file mode 100644 index 0000000000000..5046b4237ec9d --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes7.ts @@ -0,0 +1,17 @@ +/// + +/////** +//// * @param {number} x +//// * @returns {number} +//// */ +/////*1*/function f(x) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {number} x + * @returns {number} + */ +function f(x): number { +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes8.ts b/tests/cases/fourslash/convertJSDocToTypes8.ts new file mode 100644 index 0000000000000..b3d0f82183639 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes8.ts @@ -0,0 +1,17 @@ +/// + +/////** +//// * @param {number} x +//// * @returns {number} +//// */ +////var f = /*1*/function (x) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {number} x + * @returns {number} + */ +var f = function(x): number { +}`, 'Convert to Typescript type', 'convert'); diff --git a/tests/cases/fourslash/convertJSDocToTypes9.ts b/tests/cases/fourslash/convertJSDocToTypes9.ts new file mode 100644 index 0000000000000..7f682a2459c5e --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes9.ts @@ -0,0 +1,15 @@ +/// + +/////** +//// * @param {?} x +//// * @returns {number} +//// */ +////var f = /*1*/x => x + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {?} x + * @returns {number} + */ +var f = (x: any) => x`, 'Convert to Typescript type', 'convert'); From 13b37a482593340d12bfbd4a3243f18d01067d7a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 26 Sep 2017 08:58:18 -0700 Subject: [PATCH 021/246] Change refactoring name and description --- src/compiler/diagnosticMessages.json | 6 ++- src/services/refactors/convertJSDocToTypes.ts | 40 ++++++++++++------- tests/cases/fourslash/convertJSDocToTypes1.ts | 2 +- .../cases/fourslash/convertJSDocToTypes10.ts | 2 +- .../cases/fourslash/convertJSDocToTypes11.ts | 2 +- .../cases/fourslash/convertJSDocToTypes12.ts | 2 +- .../cases/fourslash/convertJSDocToTypes13.ts | 2 +- .../cases/fourslash/convertJSDocToTypes14.ts | 11 +++++ tests/cases/fourslash/convertJSDocToTypes3.ts | 6 +-- tests/cases/fourslash/convertJSDocToTypes4.ts | 14 +++---- tests/cases/fourslash/convertJSDocToTypes5.ts | 2 +- tests/cases/fourslash/convertJSDocToTypes6.ts | 2 +- tests/cases/fourslash/convertJSDocToTypes7.ts | 2 +- tests/cases/fourslash/convertJSDocToTypes8.ts | 2 +- tests/cases/fourslash/convertJSDocToTypes9.ts | 2 +- 15 files changed, 61 insertions(+), 36 deletions(-) create mode 100644 tests/cases/fourslash/convertJSDocToTypes14.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b3741af80e84f..c6024e0974c39 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3704,8 +3704,12 @@ "category": "Message", "code": 95004 }, - "Convert to Typescript type": { + "Annotate with type from JSDoc": { "category": "Message", "code": 95005 + }, + "Annotate with return type from JSDoc": { + "category": "Message", + "code": 95006 } } diff --git a/src/services/refactors/convertJSDocToTypes.ts b/src/services/refactors/convertJSDocToTypes.ts index 562c26bf50fc8..c9915d85961fe 100644 --- a/src/services/refactors/convertJSDocToTypes.ts +++ b/src/services/refactors/convertJSDocToTypes.ts @@ -1,10 +1,16 @@ /* @internal */ namespace ts.refactor.convertJSDocToTypes { - const actionName = "convert"; + const actionName = "annotate"; - const convertJSDocToTypes: Refactor = { - name: "Convert to Typescript type", - description: Diagnostics.Convert_to_Typescript_type.message, + const annotateTypeFromJSDoc: Refactor = { + name: "Annotate with type from JSDoc", + description: Diagnostics.Annotate_with_type_from_JSDoc.message, + getEditsForAction, + getAvailableActions + }; + const annotateReturnTypeFromJSDoc: Refactor = { + name: "Annotate with return type from JSDoc", + description: Diagnostics.Annotate_with_return_type_from_JSDoc.message, getEditsForAction, getAvailableActions }; @@ -16,7 +22,8 @@ namespace ts.refactor.convertJSDocToTypes { | PropertySignature | PropertyDeclaration; - registerRefactor(convertJSDocToTypes); + registerRefactor(annotateTypeFromJSDoc); + registerRefactor(annotateReturnTypeFromJSDoc); function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { if (isInJavaScriptFile(context.file)) { @@ -25,19 +32,22 @@ namespace ts.refactor.convertJSDocToTypes { const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(node, isTypedNode); - if (decl && (getJSDocType(decl) || getJSDocReturnType(decl)) && !decl.type) { - return [ - { - name: convertJSDocToTypes.name, - description: convertJSDocToTypes.description, + if (decl && !decl.type) { + const annotate = getJSDocType(decl) ? annotateTypeFromJSDoc : + getJSDocReturnType(decl) ? annotateReturnTypeFromJSDoc : + undefined; + if (annotate) { + return [{ + name: annotate.name, + description: annotate.description, actions: [ { - description: convertJSDocToTypes.description, - name: actionName - } + description: annotate.description, + name: actionName + } ] - } - ]; + }]; + } } } diff --git a/tests/cases/fourslash/convertJSDocToTypes1.ts b/tests/cases/fourslash/convertJSDocToTypes1.ts index 7f90febaca112..99cf5f8db1c15 100644 --- a/tests/cases/fourslash/convertJSDocToTypes1.ts +++ b/tests/cases/fourslash/convertJSDocToTypes1.ts @@ -7,4 +7,4 @@ verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `/** @type {number} */ -var x: number;`, 'Convert to Typescript type', 'convert'); +var x: number;`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes10.ts b/tests/cases/fourslash/convertJSDocToTypes10.ts index 1e925db81e0c3..88b565fa9328a 100644 --- a/tests/cases/fourslash/convertJSDocToTypes10.ts +++ b/tests/cases/fourslash/convertJSDocToTypes10.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x): number => x`, 'Convert to Typescript type', 'convert'); +var f = (x): number => x`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes11.ts b/tests/cases/fourslash/convertJSDocToTypes11.ts index 0315e506dc12f..63b2d85fbfe89 100644 --- a/tests/cases/fourslash/convertJSDocToTypes11.ts +++ b/tests/cases/fourslash/convertJSDocToTypes11.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('2', * @param {?} x * @returns {number} */ -var f = (x: any) => x`, 'Convert to Typescript type', 'convert'); +var f = (x: any) => x`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes12.ts b/tests/cases/fourslash/convertJSDocToTypes12.ts index 5015cb825d8da..95fa0b55cd292 100644 --- a/tests/cases/fourslash/convertJSDocToTypes12.ts +++ b/tests/cases/fourslash/convertJSDocToTypes12.ts @@ -18,4 +18,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', */ m(x): any[] { } -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes13.ts b/tests/cases/fourslash/convertJSDocToTypes13.ts index 4ee58da1caa3e..caa3315b87fb2 100644 --- a/tests/cases/fourslash/convertJSDocToTypes13.ts +++ b/tests/cases/fourslash/convertJSDocToTypes13.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `class C { /** @return {number} */ get c(): number { return 12; } -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes14.ts b/tests/cases/fourslash/convertJSDocToTypes14.ts new file mode 100644 index 0000000000000..43ac95a1c4a52 --- /dev/null +++ b/tests/cases/fourslash/convertJSDocToTypes14.ts @@ -0,0 +1,11 @@ +/// +/////** @return {number} */ +////function f() { +//// /*1*/return 12; +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** @return {number} */ +function f(): number { + return 12; +}`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes3.ts b/tests/cases/fourslash/convertJSDocToTypes3.ts index 3d3c1d35f449c..985b89ed70901 100644 --- a/tests/cases/fourslash/convertJSDocToTypes3.ts +++ b/tests/cases/fourslash/convertJSDocToTypes3.ts @@ -19,7 +19,7 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {*} beta - I have no idea how this got here */ function f(x: number, y, z: string, alpha, beta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('2'); verify.fileAfterApplyingRefactorAtMarker('2', @@ -34,7 +34,7 @@ function f(x: number, y: { a: string; b: Date; }, z: string, alpha, beta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.not.applicableRefactorAvailableAtMarker('3'); verify.not.applicableRefactorAvailableAtMarker('4'); @@ -51,4 +51,4 @@ function f(x: number, y: { a: string; b: Date; }, z: string, alpha, beta: any) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes4.ts b/tests/cases/fourslash/convertJSDocToTypes4.ts index ea80bf0452dd8..d4d5384b19c34 100644 --- a/tests/cases/fourslash/convertJSDocToTypes4.ts +++ b/tests/cases/fourslash/convertJSDocToTypes4.ts @@ -24,7 +24,7 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {number!} delta */ function f(x: any, y, z, alpha, beta, gamma, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('2'); verify.fileAfterApplyingRefactorAtMarker('2', @@ -38,7 +38,7 @@ verify.fileAfterApplyingRefactorAtMarker('2', * @param {number!} delta */ function f(x: any, y: any, z, alpha, beta, gamma, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('3'); verify.fileAfterApplyingRefactorAtMarker('3', @@ -52,7 +52,7 @@ verify.fileAfterApplyingRefactorAtMarker('3', * @param {number!} delta */ function f(x: any, y: any, z: number | undefined, alpha, beta, gamma, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('4'); verify.fileAfterApplyingRefactorAtMarker('4', `/** @@ -65,7 +65,7 @@ verify.fileAfterApplyingRefactorAtMarker('4', * @param {number!} delta */ function f(x: any, y: any, z: number | undefined, alpha: number[], beta, gamma, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('5'); verify.fileAfterApplyingRefactorAtMarker('5', @@ -81,7 +81,7 @@ verify.fileAfterApplyingRefactorAtMarker('5', function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('6'); verify.fileAfterApplyingRefactorAtMarker('6', `/** @@ -96,7 +96,7 @@ verify.fileAfterApplyingRefactorAtMarker('6', function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma: number | null, delta) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); verify.applicableRefactorAvailableAtMarker('7'); verify.fileAfterApplyingRefactorAtMarker('7', @@ -112,4 +112,4 @@ verify.fileAfterApplyingRefactorAtMarker('7', function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes5.ts b/tests/cases/fourslash/convertJSDocToTypes5.ts index 7647e7be2f8cc..1f15bf5992460 100644 --- a/tests/cases/fourslash/convertJSDocToTypes5.ts +++ b/tests/cases/fourslash/convertJSDocToTypes5.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', /** @type {number | null} */ /** @type {number | null} */ p: number | null = null; -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes6.ts b/tests/cases/fourslash/convertJSDocToTypes6.ts index 991e84b76b648..91bc1523ea301 100644 --- a/tests/cases/fourslash/convertJSDocToTypes6.ts +++ b/tests/cases/fourslash/convertJSDocToTypes6.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', /** @type {number | null} */ /** @type {number | null} */ p: number | null; -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes7.ts b/tests/cases/fourslash/convertJSDocToTypes7.ts index 5046b4237ec9d..c78f8949b18ce 100644 --- a/tests/cases/fourslash/convertJSDocToTypes7.ts +++ b/tests/cases/fourslash/convertJSDocToTypes7.ts @@ -14,4 +14,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @returns {number} */ function f(x): number { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes8.ts b/tests/cases/fourslash/convertJSDocToTypes8.ts index b3d0f82183639..502b945819ccc 100644 --- a/tests/cases/fourslash/convertJSDocToTypes8.ts +++ b/tests/cases/fourslash/convertJSDocToTypes8.ts @@ -14,4 +14,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @returns {number} */ var f = function(x): number { -}`, 'Convert to Typescript type', 'convert'); +}`, 'Annotate with return type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/convertJSDocToTypes9.ts b/tests/cases/fourslash/convertJSDocToTypes9.ts index 7f682a2459c5e..cf2581f5d8f97 100644 --- a/tests/cases/fourslash/convertJSDocToTypes9.ts +++ b/tests/cases/fourslash/convertJSDocToTypes9.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x: any) => x`, 'Convert to Typescript type', 'convert'); +var f = (x: any) => x`, 'Annotate with type from JSDoc', 'annotate'); From 96b80938909438a80d84c33ce342e7e1a45eda99 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 26 Sep 2017 09:08:39 -0700 Subject: [PATCH 022/246] Move filenames to match refactoring rename --- .../{convertJSDocToTypes.ts => annotateWithTypeFromJSDoc.ts} | 2 +- src/services/refactors/refactors.ts | 2 +- .../{convertJSDocToTypes1.ts => annotateWithTypeFromJSDoc1.ts} | 0 ...{convertJSDocToTypes10.ts => annotateWithTypeFromJSDoc10.ts} | 0 ...{convertJSDocToTypes11.ts => annotateWithTypeFromJSDoc11.ts} | 0 ...{convertJSDocToTypes12.ts => annotateWithTypeFromJSDoc12.ts} | 0 ...{convertJSDocToTypes13.ts => annotateWithTypeFromJSDoc13.ts} | 0 ...{convertJSDocToTypes14.ts => annotateWithTypeFromJSDoc14.ts} | 0 .../{convertJSDocToTypes2.ts => annotateWithTypeFromJSDoc2.ts} | 0 .../{convertJSDocToTypes3.ts => annotateWithTypeFromJSDoc3.ts} | 0 .../{convertJSDocToTypes4.ts => annotateWithTypeFromJSDoc4.ts} | 0 .../{convertJSDocToTypes5.ts => annotateWithTypeFromJSDoc5.ts} | 0 .../{convertJSDocToTypes6.ts => annotateWithTypeFromJSDoc6.ts} | 0 .../{convertJSDocToTypes7.ts => annotateWithTypeFromJSDoc7.ts} | 0 .../{convertJSDocToTypes8.ts => annotateWithTypeFromJSDoc8.ts} | 0 .../{convertJSDocToTypes9.ts => annotateWithTypeFromJSDoc9.ts} | 0 16 files changed, 2 insertions(+), 2 deletions(-) rename src/services/refactors/{convertJSDocToTypes.ts => annotateWithTypeFromJSDoc.ts} (97%) rename tests/cases/fourslash/{convertJSDocToTypes1.ts => annotateWithTypeFromJSDoc1.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes10.ts => annotateWithTypeFromJSDoc10.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes11.ts => annotateWithTypeFromJSDoc11.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes12.ts => annotateWithTypeFromJSDoc12.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes13.ts => annotateWithTypeFromJSDoc13.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes14.ts => annotateWithTypeFromJSDoc14.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes2.ts => annotateWithTypeFromJSDoc2.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes3.ts => annotateWithTypeFromJSDoc3.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes4.ts => annotateWithTypeFromJSDoc4.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes5.ts => annotateWithTypeFromJSDoc5.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes6.ts => annotateWithTypeFromJSDoc6.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes7.ts => annotateWithTypeFromJSDoc7.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes8.ts => annotateWithTypeFromJSDoc8.ts} (100%) rename tests/cases/fourslash/{convertJSDocToTypes9.ts => annotateWithTypeFromJSDoc9.ts} (100%) diff --git a/src/services/refactors/convertJSDocToTypes.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts similarity index 97% rename from src/services/refactors/convertJSDocToTypes.ts rename to src/services/refactors/annotateWithTypeFromJSDoc.ts index c9915d85961fe..d8b8e849bb608 100644 --- a/src/services/refactors/convertJSDocToTypes.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -1,5 +1,5 @@ /* @internal */ -namespace ts.refactor.convertJSDocToTypes { +namespace ts.refactor.annotateWithTypeFromJSDoc { const actionName = "annotate"; const annotateTypeFromJSDoc: Refactor = { diff --git a/src/services/refactors/refactors.ts b/src/services/refactors/refactors.ts index d1d50cb50f9d0..a536d5a8b6263 100644 --- a/src/services/refactors/refactors.ts +++ b/src/services/refactors/refactors.ts @@ -1,3 +1,3 @@ -/// +/// /// /// diff --git a/tests/cases/fourslash/convertJSDocToTypes1.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes1.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes10.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes10.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes11.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes11.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes12.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes12.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes13.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes13.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes14.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes14.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes2.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes2.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes3.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes3.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes4.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes4.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes5.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes5.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes6.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes6.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes7.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes7.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes8.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes8.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts diff --git a/tests/cases/fourslash/convertJSDocToTypes9.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts similarity index 100% rename from tests/cases/fourslash/convertJSDocToTypes9.ts rename to tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts From fc933d7c33bbc14add9f73a4639ee20439293787 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 26 Sep 2017 12:42:08 -0700 Subject: [PATCH 023/246] Transform jsdoc types in the refactor, not emitter The emitter now understands JSDoc types but emits them in the original format. --- src/compiler/emitter.ts | 39 +++-- .../refactors/annotateWithTypeFromJSDoc.ts | 109 ++++++++++-- .../fourslash/annotateWithTypeFromJSDoc15.ts | 158 ++++++++++++++++++ 3 files changed, 276 insertions(+), 30 deletions(-) create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 80b08c60d343f..61f9773c7a027 100755 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -545,8 +545,9 @@ namespace ts { case SyntaxKind.TypeReference: return emitTypeReference(node); case SyntaxKind.FunctionType: - case SyntaxKind.JSDocFunctionType: return emitFunctionType(node); + case SyntaxKind.JSDocFunctionType: + return emitJSDocFunctionType(node as JSDocFunctionType); case SyntaxKind.ConstructorType: return emitConstructorType(node); case SyntaxKind.TypeQuery: @@ -576,8 +577,10 @@ namespace ts { case SyntaxKind.LiteralType: return emitLiteralType(node); case SyntaxKind.JSDocAllType: + write("*"); + break; case SyntaxKind.JSDocUnknownType: - write("any"); + write("?"); break; case SyntaxKind.JSDocNullableType: return emitJSDocNullableType(node as JSDocNullableType); @@ -930,14 +933,13 @@ namespace ts { if (node.name) { emit(node.name); } - else if (node.parent.kind === SyntaxKind.JSDocFunctionType) { - const i = (node.parent as JSDocFunctionType).parameters.indexOf(node); - if (i > -1) { - write("arg" + i); - } - } emitIfPresent(node.questionToken); - emitWithPrefix(": ", node.type); + if (node.parent && node.parent.kind === SyntaxKind.JSDocFunctionType && !node.name) { + emit(node.type); + } + else { + emitWithPrefix(": ", node.type); + } emitExpressionWithPrefix(" = ", node.initializer); } @@ -1056,18 +1058,27 @@ namespace ts { emit(node.type); } + function emitJSDocFunctionType(node: JSDocFunctionType) { + write("function"); + emitParameters(node, node.parameters); + write(":"); + emit(node.type); + } + + function emitJSDocNullableType(node: JSDocNullableType) { + write("?"); emit(node.type); - write(" | null"); } function emitJSDocNonNullableType(node: JSDocNonNullableType) { + write("!"); emit(node.type); } function emitJSDocOptionalType(node: JSDocOptionalType) { emit(node.type); - write(" | undefined"); + write("="); } function emitConstructorType(node: ConstructorTypeNode) { @@ -1096,8 +1107,8 @@ namespace ts { } function emitJSDocVariadicType(node: JSDocVariadicType) { + write("..."); emit(node.type); - write("[]"); } function emitTupleType(node: TupleTypeNode) { @@ -2397,7 +2408,7 @@ namespace ts { emitList(parentNode, parameters, ListFormat.Parameters); } - function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType, parameters: NodeArray) { + function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { const parameter = singleOrUndefined(parameters); return parameter && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter @@ -2414,7 +2425,7 @@ namespace ts { && isIdentifier(parameter.name); // parameter name must be identifier } - function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType, parameters: NodeArray) { + function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { if (canEmitSimpleArrowHead(parentNode, parameters)) { emitList(parentNode, parameters, ListFormat.Parameters & ~ListFormat.Parenthesis); } diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index d8b8e849bb608..dde367f0ac97e 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -35,16 +35,16 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { if (decl && !decl.type) { const annotate = getJSDocType(decl) ? annotateTypeFromJSDoc : getJSDocReturnType(decl) ? annotateReturnTypeFromJSDoc : - undefined; + undefined; if (annotate) { return [{ name: annotate.name, description: annotate.description, actions: [ { - description: annotate.description, - name: actionName - } + description: annotate.description, + name: actionName + } ] }]; } @@ -62,10 +62,9 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); const decl = findAncestor(token, isTypedNode); - const jsdocType = getJSDocType(decl); - const jsdocReturn = getJSDocReturnType(decl); - if (!decl || !jsdocType && !jsdocReturn || decl.type) { - Debug.fail(`!decl || !jsdocType && !jsdocReturn || decl.type: !${decl} || !${jsdocType} && !{jsdocReturn} || ${decl.type}`); + const jsdocType = getJSDocReturnType(decl) || getJSDocType(decl); + if (!decl || !jsdocType || decl.type) { + Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); return undefined; } @@ -76,12 +75,12 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { // other syntax changes const arrow = decl.parent as ArrowFunction; const param = decl as ParameterDeclaration; - const replacementParam = createParameter(param.decorators, param.modifiers, param.dotDotDotToken, param.name, param.questionToken, jsdocType, param.initializer); + const replacementParam = createParameter(param.decorators, param.modifiers, param.dotDotDotToken, param.name, param.questionToken, transformJSDocType(jsdocType) as TypeNode, param.initializer); const replacement = createArrowFunction(arrow.modifiers, arrow.typeParameters, [replacementParam], arrow.type, arrow.equalsGreaterThanToken, arrow.body); changeTracker.replaceRange(sourceFile, { pos: arrow.getStart(), end: arrow.end }, replacement); } else { - changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, replaceType(decl, jsdocType, jsdocReturn)); + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, replaceType(decl, transformJSDocType(jsdocType) as TypeNode)); } return { edits: changeTracker.getChanges(), @@ -98,7 +97,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { node.kind === SyntaxKind.PropertyDeclaration; } - function replaceType(decl: DeclarationWithType, jsdocType: TypeNode, jsdocReturn: TypeNode) { + function replaceType(decl: DeclarationWithType, jsdocType: TypeNode) { switch (decl.kind) { case SyntaxKind.VariableDeclaration: return createVariableDeclaration(decl.name, jsdocType, decl.initializer); @@ -109,15 +108,15 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.PropertyDeclaration: return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); case SyntaxKind.FunctionDeclaration: - return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocType, decl.body); case SyntaxKind.FunctionExpression: - return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocType, decl.body); case SyntaxKind.ArrowFunction: - return createArrowFunction(decl.modifiers, decl.typeParameters, decl.parameters, jsdocReturn, decl.equalsGreaterThanToken, decl.body); + return createArrowFunction(decl.modifiers, decl.typeParameters, decl.parameters, jsdocType, decl.equalsGreaterThanToken, decl.body); case SyntaxKind.MethodDeclaration: - return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, decl.parameters, jsdocReturn, decl.body); + return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, decl.parameters, jsdocType, decl.body); case SyntaxKind.GetAccessor: - return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, jsdocReturn, decl.body); + return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, jsdocType, decl.body); default: Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`); return undefined; @@ -144,4 +143,82 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { && !parameter.initializer // parameter may not have an initializer && isIdentifier(parameter.name); // parameter name must be identifier } + + function transformJSDocType(node: Node): Node | undefined { + if (node === undefined) { + return undefined; + } + switch (node.kind) { + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + return createTypeReferenceNode("any", emptyArray); + case SyntaxKind.JSDocOptionalType: + return visitJSDocOptionalType(node as JSDocOptionalType); + case SyntaxKind.JSDocNonNullableType: + return transformJSDocType((node as JSDocNonNullableType).type); + case SyntaxKind.JSDocNullableType: + return visitJSDocNullableType(node as JSDocNullableType); + case SyntaxKind.JSDocVariadicType: + return visitJSDocVariadicType(node as JSDocVariadicType); + case SyntaxKind.JSDocFunctionType: + return visitJSDocFunctionType(node as JSDocFunctionType); + case SyntaxKind.Parameter: + return visitJSDocParameter(node as ParameterDeclaration); + case SyntaxKind.TypeReference: + return visitJSDocTypeReference(node as TypeReferenceNode); + default: + return visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode; + } + } + + function visitJSDocOptionalType(node: JSDocOptionalType) { + return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("undefined", emptyArray)]); + } + + function visitJSDocNullableType(node: JSDocNullableType) { + return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("null", emptyArray)]); + } + + function visitJSDocVariadicType(node: JSDocVariadicType) { + return createArrayTypeNode(visitNode(node.type, transformJSDocType)); + } + + function visitJSDocFunctionType(node: JSDocFunctionType) { + const parameters = node.parameters && node.parameters.map(transformJSDocType); + return createFunctionTypeNode(emptyArray, parameters as ParameterDeclaration[], node.type); + } + + function visitJSDocParameter(node: ParameterDeclaration) { + const name = node.name || "arg" + node.parent.parameters.indexOf(node); + return createParameter(node.decorators, node.modifiers, node.dotDotDotToken, name, node.questionToken, node.type, node.initializer); + } + + function visitJSDocTypeReference(node: TypeReferenceNode) { + let name = node.typeName; + let args = node.typeArguments; + if (isIdentifier(node.typeName)) { + let text = node.typeName.text; + switch (node.typeName.text) { + case "String": + case "Boolean": + case "Object": + case "Number": + text = text.toLowerCase(); + break; + case "array": + case "date": + case "promise": + text = text[0].toUpperCase() + text.slice(1); + break; + } + name = createIdentifier(text); + if ((text === "Array" || text === "Promise") && !node.typeArguments) { + args = createNodeArray([createTypeReferenceNode("any", emptyArray)]); + } + else { + args = visitNodes(node.typeArguments, transformJSDocType); + } + } + return createTypeReferenceNode(name, args); + } } diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts new file mode 100644 index 0000000000000..487b456d561f4 --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts @@ -0,0 +1,158 @@ +/// +// @strict: true +/////** +//// * @param {Boolean} x +//// * @param {String} y +//// * @param {Number} z +//// * @param {Object} alpha +//// * @param {date} beta +//// * @param {promise} gamma +//// * @param {array} delta +//// * @param {Array} epsilon +//// * @param {promise} zeta +//// */ +////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta, /*8*/epsilon, /*9*/zeta) { +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y, z, alpha, beta, gamma, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('2'); +verify.fileAfterApplyingRefactorAtMarker('2', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z, alpha, beta, gamma, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('3'); +verify.fileAfterApplyingRefactorAtMarker('3', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha, beta, gamma, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('4'); +verify.fileAfterApplyingRefactorAtMarker('4', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta, gamma, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('5'); +verify.fileAfterApplyingRefactorAtMarker('5', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('6'); +verify.fileAfterApplyingRefactorAtMarker('6', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('7'); +verify.fileAfterApplyingRefactorAtMarker('7', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('8'); +verify.fileAfterApplyingRefactorAtMarker('8', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta) { +}`, 'Annotate with type from JSDoc', 'annotate'); + +verify.applicableRefactorAvailableAtMarker('9'); +verify.fileAfterApplyingRefactorAtMarker('9', +`/** + * @param {Boolean} x + * @param {String} y + * @param {Number} z + * @param {Object} alpha + * @param {date} beta + * @param {promise} gamma + * @param {array} delta + * @param {Array} epsilon + * @param {promise} zeta + */ +function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta: Promise) { +}`, 'Annotate with type from JSDoc', 'annotate'); From 6ba62d2d8dbfcfcbf542ab3213949ed98beaf459 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 26 Sep 2017 16:29:25 -0700 Subject: [PATCH 024/246] Revert all the changes except test case --- src/compiler/program.ts | 12 ++++++------ src/compiler/types.ts | 6 +----- src/server/builder.ts | 4 ++-- src/server/project.ts | 11 +---------- src/services/services.ts | 4 ++-- src/services/transpile.ts | 2 +- src/services/types.ts | 2 +- 7 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 30c61f50dff2f..bbc0fa0978090 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -874,12 +874,12 @@ namespace ts { return oldProgram.structureIsReused = StructureIsReused.Completely; } - function getEmitHost(writeFileCallback?: WriteFileCallback, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitHost { + function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { return { getCanonicalFileName, getCommonSourceDirectory: program.getCommonSourceDirectory, getCompilerOptions: program.getCompilerOptions, - getCurrentDirectory: getCurrentDirectoryCallback || (() => currentDirectory), + getCurrentDirectory: () => currentDirectory, getNewLine: () => host.getNewLine(), getSourceFile: program.getSourceFile, getSourceFileByPath: program.getSourceFileByPath, @@ -907,15 +907,15 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } - function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult { - return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, getCurrentDirectoryCallback)); + function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers): EmitResult { + return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers)); } function isEmitBlocked(emitFileName: string): boolean { return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName)); } - function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult { + function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { let declarationDiagnostics: Diagnostic[] = []; if (options.noEmit) { @@ -960,7 +960,7 @@ namespace ts { const transformers = emitOnlyDtsFiles ? [] : getTransformers(options, customTransformers); const emitResult = emitFiles( emitResolver, - getEmitHost(writeFileCallback, getCurrentDirectoryCallback), + getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles, transformers); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ac5de15322697..ac64624e1a6aa 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2405,10 +2405,6 @@ namespace ts { (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void; } - export interface GetCurrentDirectoryCallback { - (): string; - } - export class OperationCanceledException { } export interface CancellationToken { @@ -2440,7 +2436,7 @@ namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; diff --git a/src/server/builder.ts b/src/server/builder.ts index 711045d0ae630..895732ebeceb2 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -148,9 +148,9 @@ namespace ts.server { const { emitSkipped, outputFiles } = this.project.getFileEmitOutput(fileInfo.scriptInfo, /*emitOnlyDtsFiles*/ false); if (!emitSkipped) { - const currentDirectoryForEmit = this.project.getCurrentDirectoryForScriptInfoEmit(scriptInfo); + const projectRootPath = this.project.getProjectRootPath(); for (const outputFile of outputFiles) { - const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, currentDirectoryForEmit); + const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, projectRootPath ? projectRootPath : getDirectoryPath(scriptInfo.fileName)); writeFile(outputFileAbsoluteFileName, outputFile.text, outputFile.writeByteOrderMark); } } diff --git a/src/server/project.ts b/src/server/project.ts index a7d8605315b06..ac040a77ace24 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -367,16 +367,7 @@ namespace ts.server { if (!this.languageServiceEnabled) { return undefined; } - - const getCurrentDirectoryCallback = memoize( - () => this.getCurrentDirectoryForScriptInfoEmit(info) - ); - return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles, getCurrentDirectoryCallback); - } - - getCurrentDirectoryForScriptInfoEmit(info: ScriptInfo) { - const projectRootPath = this.getProjectRootPath(); - return projectRootPath || getDirectoryPath(info.fileName); + return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles); } getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean) { diff --git a/src/services/services.ts b/src/services/services.ts index 11061181ee63c..b508285b182fb 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1528,7 +1528,7 @@ namespace ts { return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, getCurrentDirectoryCallback?: GetCurrentDirectoryCallback): EmitOutput { + function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); @@ -1543,7 +1543,7 @@ namespace ts { } const customTransformers = host.getCustomTransformers && host.getCustomTransformers(); - const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, getCurrentDirectoryCallback); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); return { outputFiles, diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 5ba393a90c946..561c188c6cdf4 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -104,7 +104,7 @@ namespace ts { addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers, /*getCurrentDirectoryCallback*/ undefined); + program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); Debug.assert(outputText !== undefined, "Output generation failed"); diff --git a/src/services/types.ts b/src/services/types.ts index 07aaaeeb4b47c..2d47da2fd1d08 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -269,7 +269,7 @@ namespace ts { getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, getCurrentDirectoryCallBack?: GetCurrentDirectoryCallback): EmitOutput; + getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; getProgram(): Program; From fad71d3dc69bc5381ba8bb17605a9660f5a05339 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 26 Sep 2017 17:29:53 -0700 Subject: [PATCH 025/246] Use project root as the current directory whenever possible to create the project --- src/compiler/program.ts | 13 +++- src/harness/unittests/compileOnSave.ts | 2 +- src/harness/unittests/session.ts | 4 +- src/server/builder.ts | 3 +- src/server/editorServices.ts | 33 ++++++++-- src/server/lsHost.ts | 4 +- src/server/project.ts | 66 +++++++++---------- tests/cases/fourslash/server/projectInfo01.ts | 8 +-- tests/cases/fourslash/server/projectInfo02.ts | 2 +- .../server/projectWithNonExistentFiles.ts | 2 +- 10 files changed, 78 insertions(+), 59 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c8ff249672506..1397d46af1cf8 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -984,11 +984,18 @@ namespace ts { return true; } - if (defaultLibraryPath && defaultLibraryPath.length !== 0) { - return containsPath(defaultLibraryPath, file.path, currentDirectory, /*ignoreCase*/ !host.useCaseSensitiveFileNames()); + if (!options.noLib) { + return false; } - return compareStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file + if (!options.lib) { + return compareStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + } + else { + return forEach(options.lib, libFileName => compareStrings(file.fileName, combinePaths(defaultLibraryPath, libFileName), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo); + } } function getDiagnosticsProducingTypeChecker() { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 89b980f23f895..dddcd64cd39a7 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -567,7 +567,7 @@ namespace ts.projectSystem { path: "/a/b/file3.js", content: "console.log('file3');" }; - const externalProjectName = "externalproject"; + const externalProjectName = "/a/b/externalproject"; const host = createServerHost([file1, file2, file3, libFile]); const session = createSession(host); const projectService = session.getProjectService(); diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index f37c9ea23920a..417591cdb6fe7 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -16,8 +16,8 @@ namespace ts.server { directoryExists: () => false, getDirectories: () => [], createDirectory: noop, - getExecutingFilePath(): string { return void 0; }, - getCurrentDirectory(): string { return void 0; }, + getExecutingFilePath(): string { return ""; }, + getCurrentDirectory(): string { return ""; }, getEnvironmentVariable(): string { return ""; }, readDirectory() { return []; }, exit: noop, diff --git a/src/server/builder.ts b/src/server/builder.ts index 5cf65611fb35d..0279f08bfab4d 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -148,9 +148,8 @@ namespace ts.server { const { emitSkipped, outputFiles } = this.project.getFileEmitOutput(fileInfo.scriptInfo, /*emitOnlyDtsFiles*/ false); if (!emitSkipped) { - const projectRootPath = this.project.getProjectRootPath(); for (const outputFile of outputFiles) { - const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, projectRootPath ? projectRootPath : getDirectoryPath(scriptInfo.fileName)); + const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, this.project.currentDirectory); writeFile(outputFileAbsoluteFileName, outputFile.text, outputFile.writeByteOrderMark); } } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d86f45a9ad997..9a12c4cab7c60 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -417,7 +417,7 @@ namespace ts.server { this.globalPlugins = opts.globalPlugins || emptyArray; this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray; this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads; - this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(this.host.getExecutingFilePath(), "../typesMap.json") : opts.typesMapLocation; + this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(this.getExecutingFilePath(), "../typesMap.json") : opts.typesMapLocation; Debug.assert(!!this.host.createHash, "'ServerHost.createHash' is required for ProjectService"); @@ -442,6 +442,16 @@ namespace ts.server { this.documentRegistry = createDocumentRegistry(this.host.useCaseSensitiveFileNames, this.host.getCurrentDirectory()); } + /*@internal*/ + getExecutingFilePath() { + return this.getNormalizedAbsolutePath(this.host.getExecutingFilePath()); + } + + /*@internal*/ + getNormalizedAbsolutePath(fileName: string) { + return getNormalizedAbsolutePath(fileName, this.host.getCurrentDirectory()); + } + /* @internal */ getChangedFiles_TestOnly() { return this.changedFiles; @@ -924,6 +934,14 @@ namespace ts.server { }); } + /*@internal*/ getScriptInfoPaths() { + const result: Path[] = []; + this.filenameToScriptInfo.forEach(info => { + result.push(info.path); + }); + return result; + } + /** * This function tries to search for a tsconfig.json for the given file. If we found it, * we first detect if there is already a configured project created for it: if so, we re-read @@ -1365,7 +1383,7 @@ namespace ts.server { return project; } } - return this.createInferredProject(/*isSingleInferredProject*/ false, projectRootPath); + return this.createInferredProject(projectRootPath, /*isSingleInferredProject*/ false, projectRootPath); } // we don't have an explicit root path, so we should try to find an inferred project @@ -1402,12 +1420,13 @@ namespace ts.server { return this.inferredProjects[0]; } - return this.createInferredProject(/*isSingleInferredProject*/ true); + // Single inferred project does not have a project root. + return this.createInferredProject(/*currentDirectory*/ undefined, /*isSingleInferredProject*/ true); } - private createInferredProject(isSingleInferredProject?: boolean, projectRootPath?: string): InferredProject { + private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: string): InferredProject { const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects; - const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath); + const project = new InferredProject(this, this.documentRegistry, compilerOptions, currentDirectory, projectRootPath); if (isSingleInferredProject) { this.inferredProjects.unshift(project); } @@ -1419,8 +1438,8 @@ namespace ts.server { createInferredProjectWithRootFileIfNecessary(root: ScriptInfo, projectRootPath?: string) { const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(root, projectRootPath) || - this.getOrCreateSingleInferredProjectIfEnabled() || - this.createInferredProject(); + this.getOrCreateSingleInferredProjectIfEnabled() || + this.createInferredProject(getDirectoryPath(root.path)); project.addRoot(root); diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 13b9505a658c0..08dd5000cba38 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -173,7 +173,7 @@ namespace ts.server { } getDefaultLibFileName() { - const nodeModuleBinDir = getDirectoryPath(normalizePath(this.host.getExecutingFilePath())); + const nodeModuleBinDir = getDirectoryPath(this.project.projectService.getExecutingFilePath()); return combinePaths(nodeModuleBinDir, getDefaultLibFileName(this.compilationSettings)); } @@ -203,7 +203,7 @@ namespace ts.server { } getCurrentDirectory(): string { - return this.host.getCurrentDirectory(); + return this.project.currentDirectory; } resolvePath(path: string): string { diff --git a/src/server/project.ts b/src/server/project.ts index 9ef79530e5125..084193a97f56f 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -177,6 +177,9 @@ namespace ts.server { return result.module; } + /*@internal*/ + readonly currentDirectory: string; + constructor( private readonly projectName: string, readonly projectKind: ProjectKind, @@ -185,8 +188,9 @@ namespace ts.server { hasExplicitListOfFiles: boolean, languageServiceEnabled: boolean, private compilerOptions: CompilerOptions, - public compileOnSaveEnabled: boolean) { - + public compileOnSaveEnabled: boolean, + currentDirectory: string | undefined) { + this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory || ""); if (!this.compilerOptions) { this.compilerOptions = getDefaultCompilerOptions(); this.compilerOptions.allowNonTsExtensions = true; @@ -268,7 +272,6 @@ namespace ts.server { getProjectName() { return this.projectName; } - abstract getProjectRootPath(): string | undefined; abstract getTypeAcquisition(): TypeAcquisition; getExternalFiles(): SortedReadonlyArray { @@ -363,7 +366,7 @@ namespace ts.server { return map(this.program.getSourceFiles(), sourceFile => { const scriptInfo = this.projectService.getScriptInfoForPath(sourceFile.path); if (!scriptInfo) { - Debug.fail(`scriptInfo for a file '${sourceFile.fileName}' is missing.`); + Debug.fail(`scriptInfo for a file '${sourceFile.fileName}' Path: '${sourceFile.path}' is missing.\nProgram currentDirectory: '${this.program.getCurrentDirectory()}'\nCurrentScriptInfos: ${this.projectService.getScriptInfoPaths()}\ncurrentDirectory: ${this.projectService.host.getCurrentDirectory()}`); } return scriptInfo; }); @@ -842,8 +845,6 @@ namespace ts.server { * the file and its imports/references are put into an InferredProject. */ export class InferredProject extends Project { - public readonly projectRootPath: string | undefined; - private static readonly newName = (() => { let nextId = 1; return () => { @@ -882,7 +883,7 @@ namespace ts.server { // Used to keep track of what directories are watched for this project directoriesWatchedForTsconfig: string[] = []; - constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, projectRootPath?: string) { + constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, currentDirectory: string | undefined, readonly projectRootPath: string | undefined) { super(InferredProject.newName(), ProjectKind.Inferred, projectService, @@ -890,7 +891,8 @@ namespace ts.server { /*files*/ undefined, /*languageServiceEnabled*/ true, compilerOptions, - /*compileOnSaveEnabled*/ false); + /*compileOnSaveEnabled*/ false, + currentDirectory); this.projectRootPath = projectRootPath; } @@ -910,15 +912,6 @@ namespace ts.server { super.removeRoot(info); } - getProjectRootPath() { - // Single inferred project does not have a project root. - if (this.projectService.useSingleInferredProject) { - return undefined; - } - const rootFiles = this.getRootFiles(); - return getDirectoryPath(rootFiles[0]); - } - close() { super.close(); @@ -962,7 +955,15 @@ namespace ts.server { private wildcardDirectories: Map, languageServiceEnabled: boolean, public compileOnSaveEnabled: boolean) { - super(configFileName, ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); + super(configFileName, + ProjectKind.Configured, + projectService, + documentRegistry, + hasExplicitListOfFiles, + languageServiceEnabled, + compilerOptions, + compileOnSaveEnabled, + getDirectoryPath(configFileName)); this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName)); this.enablePlugins(); } @@ -982,7 +983,7 @@ namespace ts.server { // Search our peer node_modules, then any globally-specified probe paths // ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/ - const searchPaths = [combinePaths(host.getExecutingFilePath(), "../../.."), ...this.projectService.pluginProbeLocations]; + const searchPaths = [combinePaths(this.projectService.getExecutingFilePath(), "../../.."), ...this.projectService.pluginProbeLocations]; if (this.projectService.allowLocalPluginLoads) { const local = getDirectoryPath(this.canonicalConfigFilePath); @@ -1062,10 +1063,6 @@ namespace ts.server { } } - getProjectRootPath() { - return getDirectoryPath(this.getConfigFilePath()); - } - setProjectErrors(projectErrors: ReadonlyArray) { this.projectErrors = projectErrors; } @@ -1196,25 +1193,22 @@ namespace ts.server { compilerOptions: CompilerOptions, languageServiceEnabled: boolean, public compileOnSaveEnabled: boolean, - private readonly projectFilePath?: string) { - super(externalProjectName, ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); - + projectFilePath?: string) { + super(externalProjectName, + ProjectKind.External, + projectService, + documentRegistry, + /*hasExplicitListOfFiles*/ true, + languageServiceEnabled, + compilerOptions, + compileOnSaveEnabled, + getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName))); } getExcludedFiles() { return this.excludedFiles; } - getProjectRootPath() { - if (this.projectFilePath) { - return getDirectoryPath(this.projectFilePath); - } - // if the projectFilePath is not given, we make the assumption that the project name - // is the path of the project file. AS the project name is provided by VS, we need to - // normalize slashes before using it as a file name. - return getDirectoryPath(normalizeSlashes(this.getProjectName())); - } - getTypeAcquisition() { return this.typeAcquisition; } diff --git a/tests/cases/fourslash/server/projectInfo01.ts b/tests/cases/fourslash/server/projectInfo01.ts index 0d8707bf8a13d..036aa5f0d4de6 100644 --- a/tests/cases/fourslash/server/projectInfo01.ts +++ b/tests/cases/fourslash/server/projectInfo01.ts @@ -14,11 +14,11 @@ ////console.log("nothing"); goTo.file("a.ts") -verify.ProjectInfo(["lib.d.ts", "a.ts"]) +verify.ProjectInfo(["/lib.d.ts", "a.ts"]) goTo.file("b.ts") -verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts"]) +verify.ProjectInfo(["/lib.d.ts", "a.ts", "b.ts"]) goTo.file("c.ts") -verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts", "c.ts"]) +verify.ProjectInfo(["/lib.d.ts", "a.ts", "b.ts", "c.ts"]) goTo.file("d.ts") -verify.ProjectInfo(["lib.d.ts", "d.ts"]) +verify.ProjectInfo(["/lib.d.ts", "d.ts"]) diff --git a/tests/cases/fourslash/server/projectInfo02.ts b/tests/cases/fourslash/server/projectInfo02.ts index 3077deb453c47..fb7c9cf8257cb 100644 --- a/tests/cases/fourslash/server/projectInfo02.ts +++ b/tests/cases/fourslash/server/projectInfo02.ts @@ -10,4 +10,4 @@ ////{ "files": ["a.ts", "b.ts"] } goTo.file("a.ts") -verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts", "tsconfig.json"]) +verify.ProjectInfo(["/lib.d.ts", "a.ts", "b.ts", "tsconfig.json"]) diff --git a/tests/cases/fourslash/server/projectWithNonExistentFiles.ts b/tests/cases/fourslash/server/projectWithNonExistentFiles.ts index 0e263d9aca6bc..a52c5f8918f9d 100644 --- a/tests/cases/fourslash/server/projectWithNonExistentFiles.ts +++ b/tests/cases/fourslash/server/projectWithNonExistentFiles.ts @@ -10,4 +10,4 @@ ////{ "files": ["a.ts", "c.ts", "b.ts"] } goTo.file("a.ts"); -verify.ProjectInfo(["lib.d.ts", "a.ts", "b.ts", "tsconfig.json"]) +verify.ProjectInfo(["/lib.d.ts", "a.ts", "b.ts", "tsconfig.json"]) From b029857528ba37ccec4d09afca69ab24cf8c8fe5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Sep 2017 20:30:10 -0700 Subject: [PATCH 026/246] Give a more helpful error message when users try decorating using expressions that take no arguments. --- src/compiler/checker.ts | 5 +++++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 9 insertions(+) mode change 100644 => 100755 src/compiler/checker.ts mode change 100644 => 100755 src/compiler/diagnosticMessages.json diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts old mode 100644 new mode 100755 index d89247b70f978..b342003cb5902 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16381,6 +16381,11 @@ namespace ts { return resolveUntypedCall(node); } + if (callSignatures.length === 1 && callSignatures[0].parameters.length === 0) { + error(node, Diagnostics.A_decorator_function_must_accept_some_number_of_arguments_but_this_expression_takes_none_Did_you_mean_to_call_it_first); + return resolveErrorCall(node); + } + const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { let errorInfo: DiagnosticMessageChain; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json old mode 100644 new mode 100755 index bf8fcdc4f84b3..193c6879b1364 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,6 +907,10 @@ "category": "Error", "code": 1328 }, + "A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first?": { + "category": "Error", + "code": 1329 + }, "Duplicate identifier '{0}'.": { "category": "Error", From fbbf3d22e398ad894be3a79c85f2769175c41826 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Sep 2017 20:56:59 -0700 Subject: [PATCH 027/246] Accepted baselines. --- tests/baselines/reference/decoratorOnClassMethod6.errors.txt | 4 ++-- .../baselines/reference/decoratorOnClassProperty11.errors.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt index 530e86117eeac..ab09a01f19bf7 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): class C { @dec ["method"]() {} ~~~~ -!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt index 2a72fefa53ede..8e778300aa6c9 100644 --- a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt +++ b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1240: Unable to resolve signature of property decorator when called as an expression. +tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts( class C { @dec prop; ~~~~ -!!! error TS1240: Unable to resolve signature of property decorator when called as an expression. +!!! error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? } \ No newline at end of file From d797b4ab7692a995662ddb11ffa7b6b83004fb13 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 28 Sep 2017 11:40:56 -0700 Subject: [PATCH 028/246] Correctly transform jsdoc parameter types And give a better name for rest params --- src/compiler/emitter.ts | 4 ++-- src/services/refactors/annotateWithTypeFromJSDoc.ts | 7 +++++-- tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts | 9 +++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 61f9773c7a027..808e8aeaf81d7 100755 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -578,10 +578,10 @@ namespace ts { return emitLiteralType(node); case SyntaxKind.JSDocAllType: write("*"); - break; + return; case SyntaxKind.JSDocUnknownType: write("?"); - break; + return; case SyntaxKind.JSDocNullableType: return emitJSDocNullableType(node as JSDocNullableType); case SyntaxKind.JSDocNonNullableType: diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index dde367f0ac97e..3111c0d3ed901 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -189,8 +189,11 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } function visitJSDocParameter(node: ParameterDeclaration) { - const name = node.name || "arg" + node.parent.parameters.indexOf(node); - return createParameter(node.decorators, node.modifiers, node.dotDotDotToken, name, node.questionToken, node.type, node.initializer); + const index = node.parent.parameters.indexOf(node); + const isRest = node.type.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; + const name = node.name || (isRest ? "rest" : "arg" + index); + const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken; + return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer); } function visitJSDocTypeReference(node: TypeReferenceNode) { diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts new file mode 100644 index 0000000000000..2f5ab2bcc72ee --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts @@ -0,0 +1,9 @@ +/// +// @strict: true +/////** @type {function(*, ...number, ...boolean): void} */ +////var /*1*/x; + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** @type {function(*, ...number, ...boolean): void} */ +var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void;`, 'Annotate with type from JSDoc', 'annotate'); From 966f370712a5c16a527ce098acad0ff175262926 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 29 Sep 2017 16:42:30 -0700 Subject: [PATCH 029/246] Use a better check. --- src/compiler/checker.ts | 15 +++++++++++++-- src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) mode change 100755 => 100644 src/compiler/checker.ts mode change 100755 => 100644 src/compiler/diagnosticMessages.json diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts old mode 100755 new mode 100644 index b342003cb5902..3760dd6a19f90 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16381,8 +16381,8 @@ namespace ts { return resolveUntypedCall(node); } - if (callSignatures.length === 1 && callSignatures[0].parameters.length === 0) { - error(node, Diagnostics.A_decorator_function_must_accept_some_number_of_arguments_but_this_expression_takes_none_Did_you_mean_to_call_it_first); + if (isPotentiallyUncalledDecorator(node, callSignatures)) { + error(node, Diagnostics.This_function_cannot_be_used_as_a_decorator_Did_you_mean_to_call_it_first); return resolveErrorCall(node); } @@ -16398,6 +16398,17 @@ namespace ts { return resolveCall(node, callSignatures, candidatesOutArray, headMessage); } + /** + * Sometimes, we have a decorator that could accept zero arguments, + * but is receiving too many arguments as part of the decorator invocation. + * In those cases, a user may have meant to *call* the expression before using it as a decorator. + */ + function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: Signature[]) { + return signatures.length && every(signatures, signature => + signature.minArgumentCount === 0 && + signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)) + } + /** * This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component. * The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json old mode 100755 new mode 100644 index 193c6879b1364..722985aac78c1 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,7 +907,7 @@ "category": "Error", "code": 1328 }, - "A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first?": { + "This function cannot be used as a decorator. Did you mean to call it first?": { "category": "Error", "code": 1329 }, From 08ef6e4bea636cdabe05fd65cd07bc40f4924b9d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 29 Sep 2017 16:42:46 -0700 Subject: [PATCH 030/246] Accepted baselines. --- src/compiler/checker.ts | 2 +- tests/baselines/reference/decoratorOnClassMethod6.errors.txt | 4 ++-- .../baselines/reference/decoratorOnClassProperty11.errors.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3760dd6a19f90..a272ac15e72e6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16406,7 +16406,7 @@ namespace ts { function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: Signature[]) { return signatures.length && every(signatures, signature => signature.minArgumentCount === 0 && - signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)) + signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)); } /** diff --git a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt index ab09a01f19bf7..befe582025c86 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: This function cannot be used as a decorator. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): class C { @dec ["method"]() {} ~~~~ -!!! error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? +!!! error TS1329: This function cannot be used as a decorator. Did you mean to call it first? } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt index 8e778300aa6c9..771ca46b572d4 100644 --- a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt +++ b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? +tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: This function cannot be used as a decorator. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts( class C { @dec prop; ~~~~ -!!! error TS1329: A decorator function must accept some number of arguments, but this expression takes none. Did you mean to call it first? +!!! error TS1329: This function cannot be used as a decorator. Did you mean to call it first? } \ No newline at end of file From 86315ed4119db22cc900b58d053f471d4d354119 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 29 Sep 2017 22:01:00 -0700 Subject: [PATCH 031/246] Added test and adjusted reporting logic. --- src/compiler/checker.ts | 3 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/emitter.ts | 0 .../compiler/potentiallyUncalledDecorators.ts | 74 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/compiler/emitter.ts create mode 100644 tests/cases/compiler/potentiallyUncalledDecorators.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a272ac15e72e6..23da94437aeaa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16382,7 +16382,7 @@ namespace ts { } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - error(node, Diagnostics.This_function_cannot_be_used_as_a_decorator_Did_you_mean_to_call_it_first); + error(node, Diagnostics.This_value_has_type_0_which_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first, typeToString(funcType)); return resolveErrorCall(node); } @@ -16406,6 +16406,7 @@ namespace ts { function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: Signature[]) { return signatures.length && every(signatures, signature => signature.minArgumentCount === 0 && + !signature.hasRestParameter && signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 722985aac78c1..57dc9f28834f0 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,7 +907,7 @@ "category": "Error", "code": 1328 }, - "This function cannot be used as a decorator. Did you mean to call it first?": { + "This value has type '{0}' which accepts too few arguments to be used as a decorator here. Did you mean to call it first?": { "category": "Error", "code": 1329 }, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts old mode 100755 new mode 100644 diff --git a/tests/cases/compiler/potentiallyUncalledDecorators.ts b/tests/cases/compiler/potentiallyUncalledDecorators.ts new file mode 100644 index 0000000000000..3c92a21eff0c4 --- /dev/null +++ b/tests/cases/compiler/potentiallyUncalledDecorators.ts @@ -0,0 +1,74 @@ +// @target: esnext +// @module: esnext +// @experimentalDecorators: true + +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +class FooComponent { + @Input foo: string; +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } + +class Person { + @tracked person; any; +} + +class MultiplyByTwo { + args: any; + @tracked('args') + get multiplied() { + return this.args.number * 2; + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +} + +declare function noArgs(): OmniDecorator; +declare function allRest(...args: any[]): OmniDecorator; +declare function oneOptional(x?: any): OmniDecorator; +declare function twoOptional(x?: any, y?: any): OmniDecorator; +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; + +@noArgs +class A { + @noArgs foo: any; + @noArgs bar() { } +} + +@allRest +class B { + @allRest foo: any; + @allRest bar() { } +} + +@oneOptional +class C { + @oneOptional foo: any; + @oneOptional bar() { } +} + +@twoOptional +class D { + @twoOptional foo: any; + @twoOptional bar() { } +} + +@threeOptional +class E { + @threeOptional foo: any; + @threeOptional bar() { } +} + +@oneOptionalWithRest +class F { + @oneOptionalWithRest foo: any; + @oneOptionalWithRest bar() { } +} + +export { }; From 803b5660fcf6b8d50b0751d76629de18c79540a3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 29 Sep 2017 22:02:35 -0700 Subject: [PATCH 032/246] Accepted baselines. --- .../decoratorOnClassMethod6.errors.txt | 4 +- .../decoratorOnClassProperty11.errors.txt | 4 +- .../potentiallyUncalledDecorators.errors.txt | 167 ++++++++++++++++ .../potentiallyUncalledDecorators.js | 170 ++++++++++++++++ .../potentiallyUncalledDecorators.symbols | 182 +++++++++++++++++ .../potentiallyUncalledDecorators.types | 188 ++++++++++++++++++ 6 files changed, 711 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/potentiallyUncalledDecorators.errors.txt create mode 100644 tests/baselines/reference/potentiallyUncalledDecorators.js create mode 100644 tests/baselines/reference/potentiallyUncalledDecorators.symbols create mode 100644 tests/baselines/reference/potentiallyUncalledDecorators.types diff --git a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt index befe582025c86..7a9e5fea35563 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: This function cannot be used as a decorator. Did you mean to call it first? +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: This value has type '() => (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): class C { @dec ["method"]() {} ~~~~ -!!! error TS1329: This function cannot be used as a decorator. Did you mean to call it first? +!!! error TS1329: This value has type '() => (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt index 771ca46b572d4..9d16d64df4104 100644 --- a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt +++ b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: This function cannot be used as a decorator. Did you mean to call it first? +tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: This value has type '() => (target: any, propertyKey: string) => void' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? ==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts( class C { @dec prop; ~~~~ -!!! error TS1329: This function cannot be used as a decorator. Did you mean to call it first? +!!! error TS1329: This value has type '() => (target: any, propertyKey: string) => void' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? } \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt new file mode 100644 index 0000000000000..e2858160ba95c --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt @@ -0,0 +1,167 @@ +tests/cases/compiler/potentiallyUncalledDecorators.ts(4,5): error TS1329: This value has type '(bindingPropertyName?: string) => any' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(34,1): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(36,5): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(37,5): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(40,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof B'. + Type 'OmniDecorator' provides no match for the signature 'new (): B'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(42,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(43,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(46,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof C'. + Type 'OmniDecorator' provides no match for the signature 'new (): C'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(48,5): error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(49,5): error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/compiler/potentiallyUncalledDecorators.ts(52,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof D'. + Type 'OmniDecorator' provides no match for the signature 'new (): D'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(54,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(55,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(58,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof E'. + Type 'OmniDecorator' provides no match for the signature 'new (): E'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(60,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(61,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(64,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof F'. + Type 'OmniDecorator' provides no match for the signature 'new (): F'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(66,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + + +==== tests/cases/compiler/potentiallyUncalledDecorators.ts (19 errors) ==== + // Angular-style Input/Output API: + declare function Input(bindingPropertyName?: string): any; + class FooComponent { + @Input foo: string; + ~~~~~~ +!!! error TS1329: This value has type '(bindingPropertyName?: string) => any' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + } + + // Glimmer-style tracked API: + declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } + + class Person { + @tracked person; any; + } + + class MultiplyByTwo { + args: any; + @tracked('args') + get multiplied() { + return this.args.number * 2; + } + } + + // Other fun stuff. + + interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { + } + + declare function noArgs(): OmniDecorator; + declare function allRest(...args: any[]): OmniDecorator; + declare function oneOptional(x?: any): OmniDecorator; + declare function twoOptional(x?: any, y?: any): OmniDecorator; + declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; + declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; + + @noArgs + ~~~~~~~ +!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + class A { + @noArgs foo: any; + ~~~~~~~ +!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + @noArgs bar() { } + ~~~~~~~ +!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + } + + @allRest + ~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof B'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): B'. + class B { + @allRest foo: any; + ~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @allRest bar() { } + ~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @oneOptional + ~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof C'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): C'. + class C { + @oneOptional foo: any; + ~~~~~~~~~~~~ +!!! error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + @oneOptional bar() { } + ~~~~~~~~~~~~ +!!! error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? + } + + @twoOptional + ~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof D'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): D'. + class D { + @twoOptional foo: any; + ~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @twoOptional bar() { } + ~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @threeOptional + ~~~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof E'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): E'. + class E { + @threeOptional foo: any; + ~~~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @threeOptional bar() { } + ~~~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @oneOptionalWithRest + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof F'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): F'. + class F { + @oneOptionalWithRest foo: any; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @oneOptionalWithRest bar() { } + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + export { }; + \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.js b/tests/baselines/reference/potentiallyUncalledDecorators.js new file mode 100644 index 0000000000000..a0dcc80ea0edf --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.js @@ -0,0 +1,170 @@ +//// [potentiallyUncalledDecorators.ts] +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +class FooComponent { + @Input foo: string; +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } + +class Person { + @tracked person; any; +} + +class MultiplyByTwo { + args: any; + @tracked('args') + get multiplied() { + return this.args.number * 2; + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +} + +declare function noArgs(): OmniDecorator; +declare function allRest(...args: any[]): OmniDecorator; +declare function oneOptional(x?: any): OmniDecorator; +declare function twoOptional(x?: any, y?: any): OmniDecorator; +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; + +@noArgs +class A { + @noArgs foo: any; + @noArgs bar() { } +} + +@allRest +class B { + @allRest foo: any; + @allRest bar() { } +} + +@oneOptional +class C { + @oneOptional foo: any; + @oneOptional bar() { } +} + +@twoOptional +class D { + @twoOptional foo: any; + @twoOptional bar() { } +} + +@threeOptional +class E { + @threeOptional foo: any; + @threeOptional bar() { } +} + +@oneOptionalWithRest +class F { + @oneOptionalWithRest foo: any; + @oneOptionalWithRest bar() { } +} + +export { }; + + +//// [potentiallyUncalledDecorators.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +class FooComponent { +} +__decorate([ + Input +], FooComponent.prototype, "foo", void 0); +class Person { +} +__decorate([ + tracked +], Person.prototype, "person", void 0); +class MultiplyByTwo { + get multiplied() { + return this.args.number * 2; + } +} +__decorate([ + tracked('args') +], MultiplyByTwo.prototype, "multiplied", null); +let A = class A { + bar() { } +}; +__decorate([ + noArgs +], A.prototype, "foo", void 0); +__decorate([ + noArgs +], A.prototype, "bar", null); +A = __decorate([ + noArgs +], A); +let B = class B { + bar() { } +}; +__decorate([ + allRest +], B.prototype, "foo", void 0); +__decorate([ + allRest +], B.prototype, "bar", null); +B = __decorate([ + allRest +], B); +let C = class C { + bar() { } +}; +__decorate([ + oneOptional +], C.prototype, "foo", void 0); +__decorate([ + oneOptional +], C.prototype, "bar", null); +C = __decorate([ + oneOptional +], C); +let D = class D { + bar() { } +}; +__decorate([ + twoOptional +], D.prototype, "foo", void 0); +__decorate([ + twoOptional +], D.prototype, "bar", null); +D = __decorate([ + twoOptional +], D); +let E = class E { + bar() { } +}; +__decorate([ + threeOptional +], E.prototype, "foo", void 0); +__decorate([ + threeOptional +], E.prototype, "bar", null); +E = __decorate([ + threeOptional +], E); +let F = class F { + bar() { } +}; +__decorate([ + oneOptionalWithRest +], F.prototype, "foo", void 0); +__decorate([ + oneOptionalWithRest +], F.prototype, "bar", null); +F = __decorate([ + oneOptionalWithRest +], F); diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.symbols b/tests/baselines/reference/potentiallyUncalledDecorators.symbols new file mode 100644 index 0000000000000..ff7cc253a27df --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.symbols @@ -0,0 +1,182 @@ +=== tests/cases/compiler/potentiallyUncalledDecorators.ts === +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +>Input : Symbol(Input, Decl(potentiallyUncalledDecorators.ts, 0, 0)) +>bindingPropertyName : Symbol(bindingPropertyName, Decl(potentiallyUncalledDecorators.ts, 1, 23)) + +class FooComponent { +>FooComponent : Symbol(FooComponent, Decl(potentiallyUncalledDecorators.ts, 1, 58)) + + @Input foo: string; +>Input : Symbol(Input, Decl(potentiallyUncalledDecorators.ts, 0, 0)) +>foo : Symbol(FooComponent.foo, Decl(potentiallyUncalledDecorators.ts, 2, 20)) +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) +>PropertyDecorator : Symbol(PropertyDecorator, Decl(lib.es5.d.ts, --, --)) +>watchedProperties : Symbol(watchedProperties, Decl(potentiallyUncalledDecorators.ts, 7, 46)) + +class Person { +>Person : Symbol(Person, Decl(potentiallyUncalledDecorators.ts, 7, 85)) + + @tracked person; any; +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) +>person : Symbol(Person.person, Decl(potentiallyUncalledDecorators.ts, 9, 14)) +>any : Symbol(Person.any, Decl(potentiallyUncalledDecorators.ts, 10, 20)) +} + +class MultiplyByTwo { +>MultiplyByTwo : Symbol(MultiplyByTwo, Decl(potentiallyUncalledDecorators.ts, 11, 1)) + + args: any; +>args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) + + @tracked('args') +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) + + get multiplied() { +>multiplied : Symbol(MultiplyByTwo.multiplied, Decl(potentiallyUncalledDecorators.ts, 14, 14)) + + return this.args.number * 2; +>this.args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) +>this : Symbol(MultiplyByTwo, Decl(potentiallyUncalledDecorators.ts, 11, 1)) +>args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) +>MethodDecorator : Symbol(MethodDecorator, Decl(lib.es5.d.ts, --, --)) +>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --)) +>PropertyDecorator : Symbol(PropertyDecorator, Decl(lib.es5.d.ts, --, --)) +} + +declare function noArgs(): OmniDecorator; +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function allRest(...args: any[]): OmniDecorator; +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>args : Symbol(args, Decl(potentiallyUncalledDecorators.ts, 27, 25)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function oneOptional(x?: any): OmniDecorator; +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 28, 29)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function twoOptional(x?: any, y?: any): OmniDecorator; +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 29, 29)) +>y : Symbol(y, Decl(potentiallyUncalledDecorators.ts, 29, 37)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 30, 31)) +>y : Symbol(y, Decl(potentiallyUncalledDecorators.ts, 30, 39)) +>z : Symbol(z, Decl(potentiallyUncalledDecorators.ts, 30, 48)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 31, 37)) +>args : Symbol(args, Decl(potentiallyUncalledDecorators.ts, 31, 45)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +@noArgs +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) + +class A { +>A : Symbol(A, Decl(potentiallyUncalledDecorators.ts, 31, 77)) + + @noArgs foo: any; +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>foo : Symbol(A.foo, Decl(potentiallyUncalledDecorators.ts, 34, 9)) + + @noArgs bar() { } +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>bar : Symbol(A.bar, Decl(potentiallyUncalledDecorators.ts, 35, 21)) +} + +@allRest +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) + +class B { +>B : Symbol(B, Decl(potentiallyUncalledDecorators.ts, 37, 1)) + + @allRest foo: any; +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>foo : Symbol(B.foo, Decl(potentiallyUncalledDecorators.ts, 40, 9)) + + @allRest bar() { } +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>bar : Symbol(B.bar, Decl(potentiallyUncalledDecorators.ts, 41, 22)) +} + +@oneOptional +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) + +class C { +>C : Symbol(C, Decl(potentiallyUncalledDecorators.ts, 43, 1)) + + @oneOptional foo: any; +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>foo : Symbol(C.foo, Decl(potentiallyUncalledDecorators.ts, 46, 9)) + + @oneOptional bar() { } +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>bar : Symbol(C.bar, Decl(potentiallyUncalledDecorators.ts, 47, 26)) +} + +@twoOptional +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) + +class D { +>D : Symbol(D, Decl(potentiallyUncalledDecorators.ts, 49, 1)) + + @twoOptional foo: any; +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>foo : Symbol(D.foo, Decl(potentiallyUncalledDecorators.ts, 52, 9)) + + @twoOptional bar() { } +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>bar : Symbol(D.bar, Decl(potentiallyUncalledDecorators.ts, 53, 26)) +} + +@threeOptional +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) + +class E { +>E : Symbol(E, Decl(potentiallyUncalledDecorators.ts, 55, 1)) + + @threeOptional foo: any; +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>foo : Symbol(E.foo, Decl(potentiallyUncalledDecorators.ts, 58, 9)) + + @threeOptional bar() { } +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>bar : Symbol(E.bar, Decl(potentiallyUncalledDecorators.ts, 59, 28)) +} + +@oneOptionalWithRest +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) + +class F { +>F : Symbol(F, Decl(potentiallyUncalledDecorators.ts, 61, 1)) + + @oneOptionalWithRest foo: any; +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>foo : Symbol(F.foo, Decl(potentiallyUncalledDecorators.ts, 64, 9)) + + @oneOptionalWithRest bar() { } +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>bar : Symbol(F.bar, Decl(potentiallyUncalledDecorators.ts, 65, 34)) +} + +export { }; + diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.types b/tests/baselines/reference/potentiallyUncalledDecorators.types new file mode 100644 index 0000000000000..d79972659d3e5 --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.types @@ -0,0 +1,188 @@ +=== tests/cases/compiler/potentiallyUncalledDecorators.ts === +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +>Input : (bindingPropertyName?: string) => any +>bindingPropertyName : string + +class FooComponent { +>FooComponent : FooComponent + + @Input foo: string; +>Input : (bindingPropertyName?: string) => any +>foo : string +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>PropertyDecorator : PropertyDecorator +>watchedProperties : string[] + +class Person { +>Person : Person + + @tracked person; any; +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>person : any +>any : any +} + +class MultiplyByTwo { +>MultiplyByTwo : MultiplyByTwo + + args: any; +>args : any + + @tracked('args') +>tracked('args') : any +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>'args' : "args" + + get multiplied() { +>multiplied : number + + return this.args.number * 2; +>this.args.number * 2 : number +>this.args.number : any +>this.args : any +>this : this +>args : any +>number : any +>2 : 2 + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +>OmniDecorator : OmniDecorator +>MethodDecorator : MethodDecorator +>ClassDecorator : ClassDecorator +>PropertyDecorator : PropertyDecorator +} + +declare function noArgs(): OmniDecorator; +>noArgs : () => OmniDecorator +>OmniDecorator : OmniDecorator + +declare function allRest(...args: any[]): OmniDecorator; +>allRest : (...args: any[]) => OmniDecorator +>args : any[] +>OmniDecorator : OmniDecorator + +declare function oneOptional(x?: any): OmniDecorator; +>oneOptional : (x?: any) => OmniDecorator +>x : any +>OmniDecorator : OmniDecorator + +declare function twoOptional(x?: any, y?: any): OmniDecorator; +>twoOptional : (x?: any, y?: any) => OmniDecorator +>x : any +>y : any +>OmniDecorator : OmniDecorator + +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>x : any +>y : any +>z : any +>OmniDecorator : OmniDecorator + +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>x : any +>args : any[] +>OmniDecorator : OmniDecorator + +@noArgs +>noArgs : () => OmniDecorator + +class A { +>A : A + + @noArgs foo: any; +>noArgs : () => OmniDecorator +>foo : any + + @noArgs bar() { } +>noArgs : () => OmniDecorator +>bar : () => void +} + +@allRest +>allRest : (...args: any[]) => OmniDecorator + +class B { +>B : B + + @allRest foo: any; +>allRest : (...args: any[]) => OmniDecorator +>foo : any + + @allRest bar() { } +>allRest : (...args: any[]) => OmniDecorator +>bar : () => void +} + +@oneOptional +>oneOptional : (x?: any) => OmniDecorator + +class C { +>C : C + + @oneOptional foo: any; +>oneOptional : (x?: any) => OmniDecorator +>foo : any + + @oneOptional bar() { } +>oneOptional : (x?: any) => OmniDecorator +>bar : () => void +} + +@twoOptional +>twoOptional : (x?: any, y?: any) => OmniDecorator + +class D { +>D : D + + @twoOptional foo: any; +>twoOptional : (x?: any, y?: any) => OmniDecorator +>foo : any + + @twoOptional bar() { } +>twoOptional : (x?: any, y?: any) => OmniDecorator +>bar : () => void +} + +@threeOptional +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator + +class E { +>E : E + + @threeOptional foo: any; +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>foo : any + + @threeOptional bar() { } +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>bar : () => void +} + +@oneOptionalWithRest +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator + +class F { +>F : F + + @oneOptionalWithRest foo: any; +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>foo : any + + @oneOptionalWithRest bar() { } +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>bar : () => void +} + +export { }; + From 96bb796730cc281a4850bfa43cffcc7929d98c6b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Oct 2017 17:56:10 -0700 Subject: [PATCH 033/246] Improve error message for uncalled decorators. --- src/compiler/checker.ts | 4 +++- src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 23da94437aeaa..c9d6c6949a962 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16382,7 +16382,9 @@ namespace ts { } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - error(node, Diagnostics.This_value_has_type_0_which_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first, typeToString(funcType)); + const printer = createPrinter({ removeComments: true }); + const nodeStr = printer.printNode(EmitHint.Expression, node.expression, getSourceFileOfNode(node)); + error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); return resolveErrorCall(node); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 57dc9f28834f0..eb508857e6f2e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,7 +907,7 @@ "category": "Error", "code": 1328 }, - "This value has type '{0}' which accepts too few arguments to be used as a decorator here. Did you mean to call it first?": { + "'{0}' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@{0}()'?": { "category": "Error", "code": 1329 }, From 392cd6117bb5c8941141e18919f051f66bf0dd5c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Oct 2017 18:00:00 -0700 Subject: [PATCH 034/246] Added a test for an 'any'-type decorator. --- tests/cases/compiler/potentiallyUncalledDecorators.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/cases/compiler/potentiallyUncalledDecorators.ts b/tests/cases/compiler/potentiallyUncalledDecorators.ts index 3c92a21eff0c4..6e537686d0f56 100644 --- a/tests/cases/compiler/potentiallyUncalledDecorators.ts +++ b/tests/cases/compiler/potentiallyUncalledDecorators.ts @@ -34,6 +34,7 @@ declare function oneOptional(x?: any): OmniDecorator; declare function twoOptional(x?: any, y?: any): OmniDecorator; declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +declare const anyDec: any; @noArgs class A { @@ -71,4 +72,10 @@ class F { @oneOptionalWithRest bar() { } } +@anyDec +class G { + @anyDec foo: any; + @anyDec bar() { } +} + export { }; From 35cfcff0d4d0861ec27049eb32fc56075ca0642c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Oct 2017 18:09:28 -0700 Subject: [PATCH 035/246] Use 'getTextOfNode'. --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c9d6c6949a962..8d8595409e83d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16382,8 +16382,7 @@ namespace ts { } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - const printer = createPrinter({ removeComments: true }); - const nodeStr = printer.printNode(EmitHint.Expression, node.expression, getSourceFileOfNode(node)); + const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false); error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); return resolveErrorCall(node); } From 7750a88957fec5c41fb286b8d59dfb4487a1b63c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Oct 2017 18:50:05 -0700 Subject: [PATCH 036/246] Accepted baselines. --- .../decoratorOnClassMethod6.errors.txt | 4 +- .../decoratorOnClassProperty11.errors.txt | 4 +- .../potentiallyUncalledDecorators.errors.txt | 57 +++++++++++-------- .../potentiallyUncalledDecorators.js | 19 +++++++ .../potentiallyUncalledDecorators.symbols | 54 ++++++++++++------ .../potentiallyUncalledDecorators.types | 18 ++++++ 6 files changed, 109 insertions(+), 47 deletions(-) diff --git a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt index 7a9e5fea35563..b863a9db72c9c 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: This value has type '() => (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): class C { @dec ["method"]() {} ~~~~ -!!! error TS1329: This value has type '() => (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt index 9d16d64df4104..537daaf44ea6a 100644 --- a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt +++ b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: This value has type '() => (target: any, propertyKey: string) => void' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? ==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts( class C { @dec prop; ~~~~ -!!! error TS1329: This value has type '() => (target: any, propertyKey: string) => void' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? } \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt index e2858160ba95c..9028ebe0377eb 100644 --- a/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt +++ b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt @@ -1,39 +1,39 @@ -tests/cases/compiler/potentiallyUncalledDecorators.ts(4,5): error TS1329: This value has type '(bindingPropertyName?: string) => any' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(34,1): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(36,5): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(37,5): error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(40,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(4,5): error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(35,1): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(37,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(38,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(41,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type 'OmniDecorator' is not assignable to type 'typeof B'. Type 'OmniDecorator' provides no match for the signature 'new (): B'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(42,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(43,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. Unable to resolve signature of property decorator when called as an expression. -tests/cases/compiler/potentiallyUncalledDecorators.ts(43,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(44,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(46,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(47,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type 'OmniDecorator' is not assignable to type 'typeof C'. Type 'OmniDecorator' provides no match for the signature 'new (): C'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(48,5): error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(49,5): error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? -tests/cases/compiler/potentiallyUncalledDecorators.ts(52,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(49,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(50,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(53,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type 'OmniDecorator' is not assignable to type 'typeof D'. Type 'OmniDecorator' provides no match for the signature 'new (): D'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(54,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(55,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. Unable to resolve signature of property decorator when called as an expression. -tests/cases/compiler/potentiallyUncalledDecorators.ts(55,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(56,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(58,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(59,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type 'OmniDecorator' is not assignable to type 'typeof E'. Type 'OmniDecorator' provides no match for the signature 'new (): E'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(60,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(61,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. Unable to resolve signature of property decorator when called as an expression. -tests/cases/compiler/potentiallyUncalledDecorators.ts(61,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(62,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(64,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(65,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type 'OmniDecorator' is not assignable to type 'typeof F'. Type 'OmniDecorator' provides no match for the signature 'new (): F'. -tests/cases/compiler/potentiallyUncalledDecorators.ts(66,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. Unable to resolve signature of property decorator when called as an expression. -tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(68,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. @@ -43,7 +43,7 @@ tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unabl class FooComponent { @Input foo: string; ~~~~~~ -!!! error TS1329: This value has type '(bindingPropertyName?: string) => any' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'? } // Glimmer-style tracked API: @@ -72,17 +72,18 @@ tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unabl declare function twoOptional(x?: any, y?: any): OmniDecorator; declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; + declare const anyDec: any; @noArgs ~~~~~~~ -!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? class A { @noArgs foo: any; ~~~~~~~ -!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? @noArgs bar() { } ~~~~~~~ -!!! error TS1329: This value has type '() => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? } @allRest @@ -109,10 +110,10 @@ tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unabl class C { @oneOptional foo: any; ~~~~~~~~~~~~ -!!! error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? @oneOptional bar() { } ~~~~~~~~~~~~ -!!! error TS1329: This value has type '(x?: any) => OmniDecorator' which accepts too few arguments to be used as a decorator here. Did you mean to call it first? +!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? } @twoOptional @@ -163,5 +164,11 @@ tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1241: Unabl !!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. } + @anyDec + class G { + @anyDec foo: any; + @anyDec bar() { } + } + export { }; \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.js b/tests/baselines/reference/potentiallyUncalledDecorators.js index a0dcc80ea0edf..b69f848a8c933 100644 --- a/tests/baselines/reference/potentiallyUncalledDecorators.js +++ b/tests/baselines/reference/potentiallyUncalledDecorators.js @@ -31,6 +31,7 @@ declare function oneOptional(x?: any): OmniDecorator; declare function twoOptional(x?: any, y?: any): OmniDecorator; declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +declare const anyDec: any; @noArgs class A { @@ -68,6 +69,12 @@ class F { @oneOptionalWithRest bar() { } } +@anyDec +class G { + @anyDec foo: any; + @anyDec bar() { } +} + export { }; @@ -168,3 +175,15 @@ __decorate([ F = __decorate([ oneOptionalWithRest ], F); +let G = class G { + bar() { } +}; +__decorate([ + anyDec +], G.prototype, "foo", void 0); +__decorate([ + anyDec +], G.prototype, "bar", null); +G = __decorate([ + anyDec +], G); diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.symbols b/tests/baselines/reference/potentiallyUncalledDecorators.symbols index ff7cc253a27df..38fe3f3dc520e 100644 --- a/tests/baselines/reference/potentiallyUncalledDecorators.symbols +++ b/tests/baselines/reference/potentiallyUncalledDecorators.symbols @@ -88,94 +88,112 @@ declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; >args : Symbol(args, Decl(potentiallyUncalledDecorators.ts, 31, 45)) >OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) +declare const anyDec: any; +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) + @noArgs >noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) class A { ->A : Symbol(A, Decl(potentiallyUncalledDecorators.ts, 31, 77)) +>A : Symbol(A, Decl(potentiallyUncalledDecorators.ts, 32, 26)) @noArgs foo: any; >noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) ->foo : Symbol(A.foo, Decl(potentiallyUncalledDecorators.ts, 34, 9)) +>foo : Symbol(A.foo, Decl(potentiallyUncalledDecorators.ts, 35, 9)) @noArgs bar() { } >noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) ->bar : Symbol(A.bar, Decl(potentiallyUncalledDecorators.ts, 35, 21)) +>bar : Symbol(A.bar, Decl(potentiallyUncalledDecorators.ts, 36, 21)) } @allRest >allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) class B { ->B : Symbol(B, Decl(potentiallyUncalledDecorators.ts, 37, 1)) +>B : Symbol(B, Decl(potentiallyUncalledDecorators.ts, 38, 1)) @allRest foo: any; >allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) ->foo : Symbol(B.foo, Decl(potentiallyUncalledDecorators.ts, 40, 9)) +>foo : Symbol(B.foo, Decl(potentiallyUncalledDecorators.ts, 41, 9)) @allRest bar() { } >allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) ->bar : Symbol(B.bar, Decl(potentiallyUncalledDecorators.ts, 41, 22)) +>bar : Symbol(B.bar, Decl(potentiallyUncalledDecorators.ts, 42, 22)) } @oneOptional >oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) class C { ->C : Symbol(C, Decl(potentiallyUncalledDecorators.ts, 43, 1)) +>C : Symbol(C, Decl(potentiallyUncalledDecorators.ts, 44, 1)) @oneOptional foo: any; >oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) ->foo : Symbol(C.foo, Decl(potentiallyUncalledDecorators.ts, 46, 9)) +>foo : Symbol(C.foo, Decl(potentiallyUncalledDecorators.ts, 47, 9)) @oneOptional bar() { } >oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) ->bar : Symbol(C.bar, Decl(potentiallyUncalledDecorators.ts, 47, 26)) +>bar : Symbol(C.bar, Decl(potentiallyUncalledDecorators.ts, 48, 26)) } @twoOptional >twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) class D { ->D : Symbol(D, Decl(potentiallyUncalledDecorators.ts, 49, 1)) +>D : Symbol(D, Decl(potentiallyUncalledDecorators.ts, 50, 1)) @twoOptional foo: any; >twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) ->foo : Symbol(D.foo, Decl(potentiallyUncalledDecorators.ts, 52, 9)) +>foo : Symbol(D.foo, Decl(potentiallyUncalledDecorators.ts, 53, 9)) @twoOptional bar() { } >twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) ->bar : Symbol(D.bar, Decl(potentiallyUncalledDecorators.ts, 53, 26)) +>bar : Symbol(D.bar, Decl(potentiallyUncalledDecorators.ts, 54, 26)) } @threeOptional >threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) class E { ->E : Symbol(E, Decl(potentiallyUncalledDecorators.ts, 55, 1)) +>E : Symbol(E, Decl(potentiallyUncalledDecorators.ts, 56, 1)) @threeOptional foo: any; >threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) ->foo : Symbol(E.foo, Decl(potentiallyUncalledDecorators.ts, 58, 9)) +>foo : Symbol(E.foo, Decl(potentiallyUncalledDecorators.ts, 59, 9)) @threeOptional bar() { } >threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) ->bar : Symbol(E.bar, Decl(potentiallyUncalledDecorators.ts, 59, 28)) +>bar : Symbol(E.bar, Decl(potentiallyUncalledDecorators.ts, 60, 28)) } @oneOptionalWithRest >oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) class F { ->F : Symbol(F, Decl(potentiallyUncalledDecorators.ts, 61, 1)) +>F : Symbol(F, Decl(potentiallyUncalledDecorators.ts, 62, 1)) @oneOptionalWithRest foo: any; >oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) ->foo : Symbol(F.foo, Decl(potentiallyUncalledDecorators.ts, 64, 9)) +>foo : Symbol(F.foo, Decl(potentiallyUncalledDecorators.ts, 65, 9)) @oneOptionalWithRest bar() { } >oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) ->bar : Symbol(F.bar, Decl(potentiallyUncalledDecorators.ts, 65, 34)) +>bar : Symbol(F.bar, Decl(potentiallyUncalledDecorators.ts, 66, 34)) +} + +@anyDec +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) + +class G { +>G : Symbol(G, Decl(potentiallyUncalledDecorators.ts, 68, 1)) + + @anyDec foo: any; +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) +>foo : Symbol(G.foo, Decl(potentiallyUncalledDecorators.ts, 71, 9)) + + @anyDec bar() { } +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) +>bar : Symbol(G.bar, Decl(potentiallyUncalledDecorators.ts, 72, 21)) } export { }; diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.types b/tests/baselines/reference/potentiallyUncalledDecorators.types index d79972659d3e5..cad861fc7b417 100644 --- a/tests/baselines/reference/potentiallyUncalledDecorators.types +++ b/tests/baselines/reference/potentiallyUncalledDecorators.types @@ -94,6 +94,9 @@ declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; >args : any[] >OmniDecorator : OmniDecorator +declare const anyDec: any; +>anyDec : any + @noArgs >noArgs : () => OmniDecorator @@ -184,5 +187,20 @@ class F { >bar : () => void } +@anyDec +>anyDec : any + +class G { +>G : G + + @anyDec foo: any; +>anyDec : any +>foo : any + + @anyDec bar() { } +>anyDec : any +>bar : () => void +} + export { }; From 686fd1e62d0ac8ed06a77029821a9bcf21329a48 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 4 Oct 2017 11:23:58 -0700 Subject: [PATCH 037/246] Fix whitespace around inserted static property Fixes #18743 --- src/services/codefixes/fixAddMissingMember.ts | 2 +- tests/cases/fourslash/codeFixAddMissingMember5.ts | 5 +++-- tests/cases/fourslash/codeFixAddMissingMember7.ts | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index a9583106fc68f..9aba4c37f682a 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -92,7 +92,7 @@ namespace ts.codefix { classDeclarationSourceFile, classDeclaration, staticInitialization, - { suffix: context.newLineCharacter }); + { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); const initializeStaticAction = { description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [tokenName]), changes: staticInitializationChangeTracker.getChanges() diff --git a/tests/cases/fourslash/codeFixAddMissingMember5.ts b/tests/cases/fourslash/codeFixAddMissingMember5.ts index 804a3910a8c5e..562c4a10f210c 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember5.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember5.ts @@ -13,11 +13,12 @@ verify.codeFix({ description: "Initialize static property 'foo'.", index: 0, - // TODO: GH#18743 and GH#18445 + // TODO: GH#18445 newFileContent: `class C { static method() { ()=>{ this.foo === 10 }; } -}C.foo = undefined;\r +}\r +C.foo = undefined;\r ` }); diff --git a/tests/cases/fourslash/codeFixAddMissingMember7.ts b/tests/cases/fourslash/codeFixAddMissingMember7.ts index 4ed9c9293d779..014ab6102dd37 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember7.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember7.ts @@ -11,9 +11,10 @@ verify.codeFix({ description: "Initialize static property 'foo'.", index: 2, - // TODO: GH#18743 and GH#18445 + // TODO: GH#18445 newFileContent: `class C { static p = ()=>{ this.foo === 10 }; -}C.foo = undefined;\r +}\r +C.foo = undefined;\r ` }); From 4cf289e1a57b7ff32d73efc7d9b36b932df926ec Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 4 Oct 2017 11:26:41 -0700 Subject: [PATCH 038/246] Fix whitespace around inserted property initializer Fixes #18741 --- src/services/codefixes/fixAddMissingMember.ts | 6 +++--- tests/cases/fourslash/codeFixAddMissingMember4.ts | 7 +++---- tests/cases/fourslash/codeFixAddMissingMember6.ts | 7 +++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 9aba4c37f682a..19bd592b7a7d6 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -112,11 +112,11 @@ namespace ts.codefix { createIdentifier("undefined"))); const propertyInitializationChangeTracker = textChanges.ChangeTracker.fromContext(context); - propertyInitializationChangeTracker.insertNodeAt( + propertyInitializationChangeTracker.insertNodeBefore( classDeclarationSourceFile, - classConstructor.body.getEnd() - 1, + classConstructor.body.getLastToken(), propertyInitialization, - { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + { suffix: context.newLineCharacter }); const initializeAction = { description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [tokenName]), diff --git a/tests/cases/fourslash/codeFixAddMissingMember4.ts b/tests/cases/fourslash/codeFixAddMissingMember4.ts index cfbec8977f677..a17b777ae5f04 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember4.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember4.ts @@ -15,12 +15,11 @@ verify.codeFix({ description: "Initialize property 'foo' in the constructor.", index: 0, - // TODO: GH#18741 and GH#18445 + // TODO: GH#18445 newFileContent: `class C { constructor() { - \r -this.foo = undefined;\r -} + this.foo = undefined;\r + } method() { this.foo === 10; } diff --git a/tests/cases/fourslash/codeFixAddMissingMember6.ts b/tests/cases/fourslash/codeFixAddMissingMember6.ts index 2598014dde5cb..32525066657a6 100644 --- a/tests/cases/fourslash/codeFixAddMissingMember6.ts +++ b/tests/cases/fourslash/codeFixAddMissingMember6.ts @@ -13,12 +13,11 @@ verify.codeFix({ description: "Initialize property 'foo' in the constructor.", index: 0, - // TODO: GH#18741 and GH#18445 + // TODO: GH#18445 newFileContent: `class C { constructor() { - \r -this.foo = undefined;\r -} + this.foo = undefined;\r + } prop = ()=>{ this.foo === 10 }; }` }); From da41217f435ca49647eb77ebafb4e293f7223bf6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Oct 2017 15:15:29 -0700 Subject: [PATCH 039/246] Binding element with parent type any is any Previously if the binding element had an initializer, then that type would be used. But this is incorrect: ```ts function f(x: any) { let { d = 1 } = x; // d should have type any not number. // f can be called with anything: } f({ d: 0 }); f({ d: 'hi' }); f({}); ``` --- src/compiler/checker.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fbe192c5629cf..347d8c911f3e4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4151,13 +4151,13 @@ namespace ts { if (parentType === unknownType) { return unknownType; } - // If no type was specified or inferred for parent, or if the specified or inferred type is any, - // infer from the initializer of the binding element if one is present. Otherwise, go with the - // undefined or any type of the parent. - if (!parentType || isTypeAny(parentType)) { - if (declaration.initializer) { - return checkDeclarationInitializer(declaration); - } + // If no type was specified or inferred for parent, + // infer from the initializer of the binding element if one is present. + // Otherwise, go with the undefined type of the parent. + if (!parentType) { + return declaration.initializer ? checkDeclarationInitializer(declaration) : parentType; + } + if (isTypeAny(parentType)) { return parentType; } @@ -4183,9 +4183,6 @@ namespace ts { // computed properties with non-literal names are treated as 'any' return anyType; } - if (declaration.initializer) { - getContextualType(declaration.initializer); - } // 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. From 2ae70a1c2bea93b2f7a589ba8cc2cb830b64cbef Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 4 Oct 2017 15:24:23 -0700 Subject: [PATCH 040/246] Update baselines --- ...cturingArrayBindingPatternAndAssignment1ES5.types | 4 ++-- ...rrayBindingPatternAndAssignment1ES5iterable.types | 4 ++-- ...cturingArrayBindingPatternAndAssignment1ES6.types | 4 ++-- ...turingObjectBindingPatternAndAssignment1ES5.types | 2 +- ...turingObjectBindingPatternAndAssignment1ES6.types | 2 +- ...ructuringObjectBindingPatternAndAssignment4.types | 12 ++++++------ tests/baselines/reference/objectRestParameter.types | 2 +- .../baselines/reference/objectRestParameterES5.types | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5.types index e2a6174e61f23..d0d8561b8080d 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5.types @@ -28,9 +28,9 @@ var [a0, a1]: any = undefined; >undefined : undefined var [a2 = false, a3 = 1]: any = undefined; ->a2 : boolean +>a2 : any >false : false ->a3 : number +>a3 : any >1 : 1 >undefined : undefined diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5iterable.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5iterable.types index a650bbad2d277..09dc481c477b8 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5iterable.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES5iterable.types @@ -28,9 +28,9 @@ var [a0, a1]: any = undefined; >undefined : undefined var [a2 = false, a3 = 1]: any = undefined; ->a2 : boolean +>a2 : any >false : false ->a3 : number +>a3 : any >1 : 1 >undefined : undefined diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES6.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES6.types index b6f54b5579983..a07ea6ca017d9 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES6.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment1ES6.types @@ -28,9 +28,9 @@ var [a0, a1]: any = undefined; >undefined : undefined var [a2 = false, a3 = 1]: any = undefined; ->a2 : boolean +>a2 : any >false : false ->a3 : number +>a3 : any >1 : 1 >undefined : undefined diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.types b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.types index e0aedcbb16709..203815fa9c866 100644 --- a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.types +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.types @@ -39,7 +39,7 @@ var {1: b3} = { 1: "string" }; >"string" : "string" var {b4 = 1}: any = { b4: 100000 }; ->b4 : number +>b4 : any >1 : 1 >{ b4: 100000 } : { b4: number; } >b4 : number diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.types b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.types index 7d68d32ac514d..1c3d1f4d00c75 100644 --- a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.types +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.types @@ -39,7 +39,7 @@ var {1: b3} = { 1: "string" }; >"string" : "string" var {b4 = 1}: any = { b4: 100000 }; ->b4 : number +>b4 : any >1 : 1 >{ b4: 100000 } : { b4: number; } >b4 : number diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment4.types b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment4.types index 24f7e8ed0ba38..104c694fbbdac 100644 --- a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment4.types +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment4.types @@ -1,20 +1,20 @@ === tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment4.ts === const { a = 1, ->a : 1 +>a : any >1 : 1 b = 2, ->b : 2 +>b : any >2 : 2 c = b, // ok ->c : 2 ->b : 2 +>c : any +>b : any d = a, // ok ->d : 1 ->a : 1 +>d : any +>a : any e = f, // error >e : any diff --git a/tests/baselines/reference/objectRestParameter.types b/tests/baselines/reference/objectRestParameter.types index 3d0d1bb619b4a..831ac9df59f9a 100644 --- a/tests/baselines/reference/objectRestParameter.types +++ b/tests/baselines/reference/objectRestParameter.types @@ -77,7 +77,7 @@ class C { } function foobar({ bar={}, ...opts }: any = {}) { >foobar : ({ bar, ...opts }?: any) => void ->bar : {} +>bar : any >{} : {} >opts : any >{} : {} diff --git a/tests/baselines/reference/objectRestParameterES5.types b/tests/baselines/reference/objectRestParameterES5.types index e0ebee3931739..1b8dd29e29ef6 100644 --- a/tests/baselines/reference/objectRestParameterES5.types +++ b/tests/baselines/reference/objectRestParameterES5.types @@ -77,7 +77,7 @@ class C { } function foobar({ bar={}, ...opts }: any = {}) { >foobar : ({ bar, ...opts }?: any) => void ->bar : {} +>bar : any >{} : {} >opts : any >{} : {} From ee05d0eb1cfadee576defbae31e8c474b9efcd9e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 4 Oct 2017 16:03:16 -0700 Subject: [PATCH 041/246] Compile public api so that all the updates are ensured to be correct --- src/harness/unittests/publicApi.ts | 34 ++++++++++++++++--- src/server/project.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/harness/unittests/publicApi.ts b/src/harness/unittests/publicApi.ts index bb37dbe9d8def..35acfec57f530 100644 --- a/src/harness/unittests/publicApi.ts +++ b/src/harness/unittests/publicApi.ts @@ -1,10 +1,34 @@ /// describe("Public APIs", () => { - it("for the language service and compiler should be acknowledged when they change", () => { - Harness.Baseline.runBaseline("api/typescript.d.ts", () => Harness.IO.readFile("built/local/typescript.d.ts")); + function verifyApi(fileName: string) { + const builtFile = `built/local/${fileName}`; + const api = `api/${fileName}`; + let fileContent: string; + before(() => { + fileContent = Harness.IO.readFile(builtFile); + }); + + it("should be acknowledged when they change", () => { + Harness.Baseline.runBaseline(api, () => fileContent); + }); + + it("should compile", () => { + const testFile: Harness.Compiler.TestFile = { + unitName: builtFile, + content: fileContent + }; + const inputFiles = [testFile]; + const output = Harness.Compiler.compileFiles(inputFiles, [], /*harnessSettings*/ undefined, /*options*/ {}, /*currentDirectory*/ undefined); + assert(!output.result.errors || !output.result.errors.length, Harness.Compiler.minimalDiagnosticsToString(output.result.errors, /*pretty*/ true)); + }); + } + + describe("for the language service and compiler", () => { + verifyApi("typescript.d.ts"); }); - it("for the language server should be acknowledged when they change", () => { - Harness.Baseline.runBaseline("api/tsserverlibrary.d.ts", () => Harness.IO.readFile("built/local/tsserverlibrary.d.ts")); + + describe("for the language server", () => { + verifyApi("tsserverlibrary.d.ts"); }); -}); \ No newline at end of file +}); diff --git a/src/server/project.ts b/src/server/project.ts index 655f3ed0cfcaf..ac18738027b65 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -296,7 +296,7 @@ namespace ts.server { } } - getCancellationToken() { + getCancellationToken(): HostCancellationToken { return this.cancellationToken; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1feb6b7d073f6..3bb2ed1167488 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7104,7 +7104,7 @@ declare namespace ts.server { getScriptKind(fileName: string): ScriptKind; getScriptVersion(filename: string): string; getScriptSnapshot(filename: string): IScriptSnapshot; - getCancellationToken(): ThrottledCancellationToken; + getCancellationToken(): HostCancellationToken; getCurrentDirectory(): string; getDefaultLibFileName(): string; useCaseSensitiveFileNames(): boolean; From 249725d4b72a0dcdd5524457c813330002ed07a3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 4 Oct 2017 13:25:56 -0700 Subject: [PATCH 042/246] Do not report config file errors if the file opened isnt from configured project and that project doesnt have the config errors Fixes #16635 --- src/harness/unittests/telemetry.ts | 34 +++++++--- .../unittests/tsserverProjectSystem.ts | 67 ++++++++++++++++++- src/server/editorServices.ts | 28 +++++--- src/server/project.ts | 6 +- src/server/session.ts | 8 +-- .../reference/api/tsserverlibrary.d.ts | 1 + 6 files changed, 116 insertions(+), 28 deletions(-) diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index 7c09806632180..d2a54fdc1bb96 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -7,7 +7,7 @@ namespace ts.projectSystem { const file = makeFile("/a.js"); const et = new EventTracker([file]); et.service.openClientFile(file.path); - assert.equal(et.getEvents().length, 0); + assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); }); it("only sends an event once", () => { @@ -25,12 +25,12 @@ namespace ts.projectSystem { et.service.openClientFile(file2.path); checkNumberOfProjects(et.service, { inferredProjects: 1 }); - assert.equal(et.getEvents().length, 0); + assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); et.service.openClientFile(file.path); checkNumberOfProjects(et.service, { configuredProjects: 1, inferredProjects: 1 }); - assert.equal(et.getEvents().length, 0); + assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); }); it("counts files by extension", () => { @@ -219,7 +219,7 @@ namespace ts.projectSystem { const et = new EventTracker([tsconfig, file]); et.host.getFileSize = () => server.maxProgramSizeForNonTsFiles + 1; et.service.openClientFile(file.path); - et.getEvent(server.ProjectLanguageServiceStateEvent, /*mayBeMore*/ true); + et.getEvent(server.ProjectLanguageServiceStateEvent); et.assertProjectInfoTelemetryEvent({ projectId: Harness.mockHash("/jsconfig.json"), fileStats: fileStats({ js: 1 }), @@ -255,6 +255,17 @@ namespace ts.projectSystem { return events; } + getEventsWithName(eventName: T["eventName"]): ReadonlyArray { + let events: T[]; + removeWhere(this.events, event => { + if (event.eventName === eventName) { + (events || (events = [])).push(event as T); + return true; + } + }); + return events || emptyArray; + } + assertProjectInfoTelemetryEvent(partial: Partial, configFile?: string): void { assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), { projectId: Harness.mockHash(configFile || "/tsconfig.json"), @@ -278,10 +289,17 @@ namespace ts.projectSystem { }); } - getEvent(eventName: T["eventName"], mayBeMore = false): T["data"] { - if (mayBeMore) { assert(this.events.length !== 0); } - else { assert.equal(this.events.length, 1); } - const event = this.events.shift(); + getEvent(eventName: T["eventName"]): T["data"] { + let event: server.ProjectServiceEvent; + removeWhere(this.events, e => { + if (e.eventName === eventName) { + if (event) { + assert(false, "more than one event found"); + } + event = e; + return true; + } + }); assert.equal(event.eventName, eventName); return event.data; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 06e2beeaaa6cf..e8b18ea3b5498 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -463,7 +463,7 @@ namespace ts.projectSystem { const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); - assert.isTrue(!configFileErrors, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); + assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); checkNumberOfInferredProjects(projectService, 0); checkNumberOfConfiguredProjects(projectService, 1); @@ -503,7 +503,7 @@ namespace ts.projectSystem { const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); - assert.isTrue(!configFileErrors, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); + assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); checkNumberOfInferredProjects(projectService, 0); checkNumberOfConfiguredProjects(projectService, 1); @@ -3169,6 +3169,69 @@ namespace ts.projectSystem { host.runQueuedTimeoutCallbacks(); serverEventManager.checkEventCountOfType("configFileDiag", 3); }); + + it("are generated when the config file doesnot include file opened but has errors", () => { + const serverEventManager = new TestServerEventManager(); + const file = { + path: "/a/b/app.ts", + content: "let x = 10" + }; + const file2 = { + path: "/a/b/test.ts", + content: "let x = 10" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: `{ + "compilerOptions": { + "foo": "bar", + "allowJS": true + }, + "files": ["app.ts"] + }` + }; + + const host = createServerHost([file, file2, libFile, configFile]); + const session = createSession(host, { + canUseEvents: true, + eventHandler: serverEventManager.handler + }); + openFilesForSession([file2], session); + serverEventManager.checkEventCountOfType("configFileDiag", 1); + for (const event of serverEventManager.events) { + if (event.eventName === "configFileDiag") { + assert.equal(event.data.configFileName, configFile.path); + assert.equal(event.data.triggerFile, file2.path); + return; + } + } + }); + + it("are not generated when the config file doesnot include file opened and doesnt contain any errors", () => { + const serverEventManager = new TestServerEventManager(); + const file = { + path: "/a/b/app.ts", + content: "let x = 10" + }; + const file2 = { + path: "/a/b/test.ts", + content: "let x = 10" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: `{ + "files": ["app.ts"] + }` + }; + + const host = createServerHost([file, file2, libFile, configFile]); + const session = createSession(host, { + canUseEvents: true, + eventHandler: serverEventManager.handler + }); + openFilesForSession([file2], session); + serverEventManager.checkEventCountOfType("configFileDiag", 0); + }); }); describe("skipLibCheck", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 25a285929bef2..32358ba3c4c3d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1561,14 +1561,17 @@ namespace ts.server { project.watchWildcards(projectOptions.wildcardDirectories); } this.updateNonInferredProject(project, projectOptions.files, fileNamePropertyReader, projectOptions.compilerOptions, projectOptions.typeAcquisition, projectOptions.compileOnSave); + this.sendConfigFileDiagEvent(project, configFileName); + } + private sendConfigFileDiagEvent(project: ConfiguredProject, triggerFile: NormalizedPath) { if (!this.eventHandler) { return; } this.eventHandler({ eventName: ConfigFileDiagEvent, - data: { configFileName, diagnostics: project.getGlobalProjectErrors() || [], triggerFile: configFileName } + data: { configFileName: project.getConfigFilePath(), diagnostics: project.getAllProjectErrors(), triggerFile } }); } @@ -1888,6 +1891,7 @@ namespace ts.server { openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult { let configFileName: NormalizedPath; + let sendConfigFileDiagEvent = false; let configFileErrors: ReadonlyArray; const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, fileContent, scriptKind, hasMixedContent); @@ -1898,14 +1902,8 @@ namespace ts.server { project = this.findConfiguredProjectByProjectName(configFileName); if (!project) { project = this.createConfiguredProject(configFileName); - - // even if opening config file was successful, it could still - // contain errors that were tolerated. - const errors = project.getGlobalProjectErrors(); - if (errors && errors.length > 0) { - // set configFileErrors only when the errors array is non-empty - configFileErrors = errors; - } + // Send the event only if the project got created as part of this open request + sendConfigFileDiagEvent = true; } } } @@ -1919,10 +1917,21 @@ namespace ts.server { // At this point if file is part of any any configured or external project, then it would be present in the containing projects // So if it still doesnt have any containing projects, it needs to be part of inferred project if (info.isOrphan()) { + // Since the file isnt part of configured project, + // report config file and its error only if config file found had errors (and hence may be didnt include the file) + if (sendConfigFileDiagEvent && !project.getAllProjectErrors().length) { + configFileName = undefined; + sendConfigFileDiagEvent = false; + } this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); } this.addToListOfOpenFiles(info); + if (sendConfigFileDiagEvent) { + configFileErrors = project.getAllProjectErrors(); + this.sendConfigFileDiagEvent(project as ConfiguredProject, fileName); + } + // Remove the configured projects that have zero references from open files. // This was postponed from closeOpenFile to after opening next file, // so that we can reuse the project if we need to right away @@ -1938,6 +1947,7 @@ namespace ts.server { // the file from that old project is reopened because of opening file from here. this.deleteOrphanScriptInfoNotInAnyProject(); this.printProjects(); + return { configFileName, configFileErrors }; } diff --git a/src/server/project.ts b/src/server/project.ts index 655f3ed0cfcaf..203355ad9db16 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1271,14 +1271,14 @@ namespace ts.server { * Get the errors that dont have any file name associated */ getGlobalProjectErrors(): ReadonlyArray { - return filter(this.projectErrors, diagnostic => !diagnostic.file); + return filter(this.projectErrors, diagnostic => !diagnostic.file) || emptyArray; } /** * Get all the project errors */ getAllProjectErrors(): ReadonlyArray { - return this.projectErrors; + return this.projectErrors || emptyArray; } setProjectErrors(projectErrors: Diagnostic[]) { @@ -1335,6 +1335,8 @@ namespace ts.server { } this.stopWatchingWildCards(); + this.projectErrors = undefined; + this.configFileSpecs = undefined; } addOpenRef() { diff --git a/src/server/session.ts b/src/server/session.ts index 57dac7ec799a0..59762f8191b81 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -969,13 +969,7 @@ namespace ts.server { * @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: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: NormalizedPath) { - const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath); - if (this.eventHandler) { - this.eventHandler({ - eventName: "configFileDiag", - data: { triggerFile: fileName, configFileName, diagnostics: configFileErrors || emptyArray } - }); - } + this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath); } private getPosition(args: protocol.FileLocationRequestArgs, scriptInfo: ScriptInfo): number { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1feb6b7d073f6..b9b72dec922af 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7517,6 +7517,7 @@ declare namespace ts.server { private createConfiguredProject(configFileName); private updateNonInferredProjectFiles(project, files, propertyReader); private updateNonInferredProject(project, newUncheckedFiles, propertyReader, newOptions, newTypeAcquisition, compileOnSave); + private sendConfigFileDiagEvent(project, triggerFile); private getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath); private getOrCreateSingleInferredProjectIfEnabled(); private createInferredProject(rootDirectoryForResolution, isSingleInferredProject?, projectRootPath?); From bf4ca30bc30b273f9bae31a2992a8c2481d8a850 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 4 Oct 2017 17:29:06 -0700 Subject: [PATCH 043/246] Let builder find out from imports/typereference directives if file references have changed. This is needed to ensure that the ambient module addition takes effect Fixes #15632 --- src/compiler/builder.ts | 7 +- src/compiler/program.ts | 3 +- src/compiler/types.ts | 2 - src/harness/unittests/tscWatchMode.ts | 142 ++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 8 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 6bb94ea2de7ee..03eb5b7e8aee9 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -77,8 +77,8 @@ namespace ts { */ onUpdateSourceFile(program: Program, sourceFile: SourceFile): void; /** - * Called when source file has not changed but has some of the resolutions invalidated - * If returned true, builder will mark the file as changed (noting that something associated with file has changed) + * Called when source file has not changed + * If returned true, builder will mark the file as changed (noting that something associated with file has changed eg. module resolution) */ onUpdateSourceFileWithSameVersion(program: Program, sourceFile: SourceFile): boolean; /** @@ -161,8 +161,7 @@ namespace ts { existingInfo.version = sourceFile.version; emitHandler.onUpdateSourceFile(program, sourceFile); } - else if (program.hasInvalidatedResolution(sourceFile.path) && - emitHandler.onUpdateSourceFileWithSameVersion(program, sourceFile)) { + else if (emitHandler.onUpdateSourceFileWithSameVersion(program, sourceFile)) { registerChangedFile(sourceFile.path, sourceFile.fileName); } } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 24d7707f50d62..757e7827f2758 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -663,8 +663,7 @@ namespace ts { dropDiagnosticsProducingTypeChecker, getSourceFileFromReference, sourceFileToPackageName, - redirectTargetsSet, - hasInvalidatedResolution + redirectTargetsSet }; verifyCompilerOptions(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 578c2d23c4f39..a6fccabd4dc7b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2525,8 +2525,6 @@ namespace ts { /* @internal */ sourceFileToPackageName: Map; /** Set of all source files that some other source file redirects to. */ /* @internal */ redirectTargetsSet: Map; - /** Returns true when file in the program had invalidated resolution at the time of program creation. */ - /* @internal */ hasInvalidatedResolution: HasInvalidatedResolution; } /* @internal */ diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 5267bbcf0478c..31d79df21c13b 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1655,5 +1655,147 @@ namespace ts.tscWatch { assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called."); checkOutputDoesNotContain(host, [barNotFound]); }); + + it("works when module resolution changes to ambient module", () => { + const root = { + path: "/a/b/foo.ts", + content: `import * as fs from "fs";` + }; + + const packageJson = { + path: "/a/b/node_modules/@types/node/package.json", + content: ` +{ + "main": "" +} +` + }; + + const nodeType = { + path: "/a/b/node_modules/@types/node/index.d.ts", + content: ` +declare module "fs" { + export interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atimeMs: number; + mtimeMs: number; + ctimeMs: number; + birthtimeMs: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } +}` + }; + + const files = [root, libFile]; + const filesWithNodeType = files.concat(packageJson, nodeType); + const host = createWatchedSystem(files, { currentDirectory: "/a/b" }); + + createWatchModeWithoutConfigFile([root.path], host, { }); + + const fsNotFound = `foo.ts(1,21): error TS2307: Cannot find module 'fs'.\n`; + checkOutputContains(host, [fsNotFound]); + host.clearOutput(); + + host.reloadFS(filesWithNodeType); + host.runQueuedTimeoutCallbacks(); + checkOutputDoesNotContain(host, [fsNotFound]); + }); + + it("works when included file with ambient module changes", () => { + const root = { + path: "/a/b/foo.ts", + content: ` +import * as fs from "fs"; +import * as u from "url"; +` + }; + + const file = { + path: "/a/b/bar.d.ts", + content: ` +declare module "url" { + export interface Url { + href?: string; + protocol?: string; + auth?: string; + hostname?: string; + port?: string; + host?: string; + pathname?: string; + search?: string; + query?: string | any; + slashes?: boolean; + hash?: string; + path?: string; + } +} +` + }; + + const fileContentWithFS = ` +declare module "fs" { + export interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atimeMs: number; + mtimeMs: number; + ctimeMs: number; + birthtimeMs: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } +} +`; + + const files = [root, file, libFile]; + const host = createWatchedSystem(files, { currentDirectory: "/a/b" }); + + createWatchModeWithoutConfigFile([root.path, file.path], host, {}); + + const fsNotFound = `foo.ts(2,21): error TS2307: Cannot find module 'fs'.\n`; + checkOutputContains(host, [fsNotFound]); + host.clearOutput(); + + file.content += fileContentWithFS; + host.reloadFS(files); + host.runQueuedTimeoutCallbacks(); + checkOutputDoesNotContain(host, [fsNotFound]); + }); }); } From b69652b137c280b16f7325b8dedd3bf029339f27 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 5 Oct 2017 09:01:39 -0700 Subject: [PATCH 044/246] Set symbol on union of spreads Previously, it was only set on the top-level type, and only if that top-level type was an object type. Now it uses `forEachType` to set the symbol on every object type in the union as well, if `getSpreadType` returns a union. --- src/compiler/checker.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fbe192c5629cf..d7585bd6e9a80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13917,13 +13917,15 @@ namespace ts { if (propertiesArray.length > 0) { spread = getSpreadType(spread, createObjectLiteralType()); } - if (spread.flags & TypeFlags.Object) { - // only set the symbol and flags if this is a (fresh) object type - spread.flags |= propagatedFlags; - spread.flags |= TypeFlags.FreshLiteral; - (spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; - spread.symbol = node.symbol; - } + // only set the symbol and flags if this is a (fresh) object type + forEachType(spread, t => { + if (t.flags & TypeFlags.Object) { + t.flags |= propagatedFlags; + t.flags |= TypeFlags.FreshLiteral; + (t as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; + t.symbol = node.symbol + } + }); return spread; } From 0cb12b32a5abbe37b847fd93c94a435319480e61 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 5 Oct 2017 09:03:03 -0700 Subject: [PATCH 045/246] Test:{} in union from spread gets implicit index signature Also tighten up the existing test code in the file. --- .../objectSpreadIndexSignature.errors.txt | 19 ++++++ .../reference/objectSpreadIndexSignature.js | 28 ++++----- .../objectSpreadIndexSignature.symbols | 63 +++++++++---------- .../objectSpreadIndexSignature.types | 52 +++++++-------- .../spread/objectSpreadIndexSignature.ts | 21 +++---- 5 files changed, 96 insertions(+), 87 deletions(-) create mode 100644 tests/baselines/reference/objectSpreadIndexSignature.errors.txt diff --git a/tests/baselines/reference/objectSpreadIndexSignature.errors.txt b/tests/baselines/reference/objectSpreadIndexSignature.errors.txt new file mode 100644 index 0000000000000..ee7425909c29f --- /dev/null +++ b/tests/baselines/reference/objectSpreadIndexSignature.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts(6,1): error TS7017: Element implicitly has an 'any' type because type '{ b: number; a: number; }' has no index signature. + + +==== tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts (1 errors) ==== + declare let indexed1: { [n: string]: number; a: number; }; + declare let indexed2: { [n: string]: boolean; c: boolean; }; + declare let indexed3: { [n: string]: number }; + let i = { ...indexed1, b: 11 }; + // only indexed has indexer, so i[101]: any + i[101]; + ~~~~~~ +!!! error TS7017: Element implicitly has an 'any' type because type '{ b: number; a: number; }' has no index signature. + let ii = { ...indexed1, ...indexed2 }; + // both have indexer, so i[1001]: number | boolean + ii[1001]; + + declare const b: boolean; + indexed3 = { ...b ? indexed3 : undefined }; + \ No newline at end of file diff --git a/tests/baselines/reference/objectSpreadIndexSignature.js b/tests/baselines/reference/objectSpreadIndexSignature.js index 22e92e6a844bf..283129036daeb 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.js +++ b/tests/baselines/reference/objectSpreadIndexSignature.js @@ -1,23 +1,20 @@ //// [objectSpreadIndexSignature.ts] -interface Indexed { - [n: string]: number; - a: number; -} -interface Indexed2 { - [n: string]: boolean; - c: boolean; -} -let indexed: Indexed; -let indexed2: Indexed2; -let i = { ...indexed, b: 11 }; +declare let indexed1: { [n: string]: number; a: number; }; +declare let indexed2: { [n: string]: boolean; c: boolean; }; +declare let indexed3: { [n: string]: number }; +let i = { ...indexed1, b: 11 }; // only indexed has indexer, so i[101]: any i[101]; -let ii = { ...indexed, ...indexed2 }; +let ii = { ...indexed1, ...indexed2 }; // both have indexer, so i[1001]: number | boolean ii[1001]; + +declare const b: boolean; +indexed3 = { ...b ? indexed3 : undefined }; //// [objectSpreadIndexSignature.js] +"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; @@ -26,11 +23,10 @@ var __assign = (this && this.__assign) || Object.assign || function(t) { } return t; }; -var indexed; -var indexed2; -var i = __assign({}, indexed, { b: 11 }); +var i = __assign({}, indexed1, { b: 11 }); // only indexed has indexer, so i[101]: any i[101]; -var ii = __assign({}, indexed, indexed2); +var ii = __assign({}, indexed1, indexed2); // both have indexer, so i[1001]: number | boolean ii[1001]; +indexed3 = __assign({}, b ? indexed3 : undefined); diff --git a/tests/baselines/reference/objectSpreadIndexSignature.symbols b/tests/baselines/reference/objectSpreadIndexSignature.symbols index cd64b15719699..d08cfff53ff8b 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.symbols +++ b/tests/baselines/reference/objectSpreadIndexSignature.symbols @@ -1,45 +1,42 @@ === tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === -interface Indexed { ->Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0)) +declare let indexed1: { [n: string]: number; a: number; }; +>indexed1 : Symbol(indexed1, Decl(objectSpreadIndexSignature.ts, 0, 11)) +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 0, 25)) +>a : Symbol(a, Decl(objectSpreadIndexSignature.ts, 0, 44)) - [n: string]: number; ->n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 1, 5)) +declare let indexed2: { [n: string]: boolean; c: boolean; }; +>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 1, 11)) +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 1, 25)) +>c : Symbol(c, Decl(objectSpreadIndexSignature.ts, 1, 45)) - a: number; ->a : Symbol(Indexed.a, Decl(objectSpreadIndexSignature.ts, 1, 24)) -} -interface Indexed2 { ->Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1)) +declare let indexed3: { [n: string]: number }; +>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11)) +>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 2, 25)) - [n: string]: boolean; ->n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 5, 5)) - - c: boolean; ->c : Symbol(Indexed2.c, Decl(objectSpreadIndexSignature.ts, 5, 25)) -} -let indexed: Indexed; ->indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3)) ->Indexed : Symbol(Indexed, Decl(objectSpreadIndexSignature.ts, 0, 0)) - -let indexed2: Indexed2; ->indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 9, 3)) ->Indexed2 : Symbol(Indexed2, Decl(objectSpreadIndexSignature.ts, 3, 1)) - -let i = { ...indexed, b: 11 }; ->i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3)) ->indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3)) ->b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 21)) +let i = { ...indexed1, b: 11 }; +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 3, 3)) +>indexed1 : Symbol(indexed1, Decl(objectSpreadIndexSignature.ts, 0, 11)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 3, 22)) // only indexed has indexer, so i[101]: any i[101]; ->i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 10, 3)) +>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 3, 3)) -let ii = { ...indexed, ...indexed2 }; ->ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3)) ->indexed : Symbol(indexed, Decl(objectSpreadIndexSignature.ts, 8, 3)) ->indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 9, 3)) +let ii = { ...indexed1, ...indexed2 }; +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 6, 3)) +>indexed1 : Symbol(indexed1, Decl(objectSpreadIndexSignature.ts, 0, 11)) +>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 1, 11)) // both have indexer, so i[1001]: number | boolean ii[1001]; ->ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 13, 3)) +>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 6, 3)) + +declare const b: boolean; +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 13)) + +indexed3 = { ...b ? indexed3 : undefined }; +>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11)) +>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 13)) +>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11)) +>undefined : Symbol(undefined) diff --git a/tests/baselines/reference/objectSpreadIndexSignature.types b/tests/baselines/reference/objectSpreadIndexSignature.types index 5eebc2ffa02b7..eff3b04b8f618 100644 --- a/tests/baselines/reference/objectSpreadIndexSignature.types +++ b/tests/baselines/reference/objectSpreadIndexSignature.types @@ -1,34 +1,22 @@ === tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts === -interface Indexed { ->Indexed : Indexed - - [n: string]: number; +declare let indexed1: { [n: string]: number; a: number; }; +>indexed1 : { [n: string]: number; a: number; } >n : string - - a: number; >a : number -} -interface Indexed2 { ->Indexed2 : Indexed2 - [n: string]: boolean; +declare let indexed2: { [n: string]: boolean; c: boolean; }; +>indexed2 : { [n: string]: boolean; c: boolean; } >n : string - - c: boolean; >c : boolean -} -let indexed: Indexed; ->indexed : Indexed ->Indexed : Indexed -let indexed2: Indexed2; ->indexed2 : Indexed2 ->Indexed2 : Indexed2 +declare let indexed3: { [n: string]: number }; +>indexed3 : { [n: string]: number; } +>n : string -let i = { ...indexed, b: 11 }; +let i = { ...indexed1, b: 11 }; >i : { b: number; a: number; } ->{ ...indexed, b: 11 } : { b: number; a: number; } ->indexed : Indexed +>{ ...indexed1, b: 11 } : { b: number; a: number; } +>indexed1 : { [n: string]: number; a: number; } >b : number >11 : 11 @@ -38,11 +26,11 @@ i[101]; >i : { b: number; a: number; } >101 : 101 -let ii = { ...indexed, ...indexed2 }; +let ii = { ...indexed1, ...indexed2 }; >ii : { [x: string]: number | boolean; c: boolean; a: number; } ->{ ...indexed, ...indexed2 } : { [x: string]: number | boolean; c: boolean; a: number; } ->indexed : Indexed ->indexed2 : Indexed2 +>{ ...indexed1, ...indexed2 } : { [x: string]: number | boolean; c: boolean; a: number; } +>indexed1 : { [n: string]: number; a: number; } +>indexed2 : { [n: string]: boolean; c: boolean; } // both have indexer, so i[1001]: number | boolean ii[1001]; @@ -50,3 +38,15 @@ ii[1001]; >ii : { [x: string]: number | boolean; c: boolean; a: number; } >1001 : 1001 +declare const b: boolean; +>b : boolean + +indexed3 = { ...b ? indexed3 : undefined }; +>indexed3 = { ...b ? indexed3 : undefined } : {} | { [n: string]: number; } +>indexed3 : { [n: string]: number; } +>{ ...b ? indexed3 : undefined } : {} | { [n: string]: number; } +>b ? indexed3 : undefined : { [n: string]: number; } | undefined +>b : boolean +>indexed3 : { [n: string]: number; } +>undefined : undefined + diff --git a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts index ae46f2547d54c..83649d465f183 100644 --- a/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts +++ b/tests/cases/conformance/types/spread/objectSpreadIndexSignature.ts @@ -1,16 +1,13 @@ -interface Indexed { - [n: string]: number; - a: number; -} -interface Indexed2 { - [n: string]: boolean; - c: boolean; -} -let indexed: Indexed; -let indexed2: Indexed2; -let i = { ...indexed, b: 11 }; +// @strict: true +declare let indexed1: { [n: string]: number; a: number; }; +declare let indexed2: { [n: string]: boolean; c: boolean; }; +declare let indexed3: { [n: string]: number }; +let i = { ...indexed1, b: 11 }; // only indexed has indexer, so i[101]: any i[101]; -let ii = { ...indexed, ...indexed2 }; +let ii = { ...indexed1, ...indexed2 }; // both have indexer, so i[1001]: number | boolean ii[1001]; + +declare const b: boolean; +indexed3 = { ...b ? indexed3 : undefined }; From 97ee9516d671eb52fe96fa6694f6a2bbe12fcf29 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 5 Oct 2017 09:10:55 -0700 Subject: [PATCH 046/246] Update baselines --- .../excessPropertyCheckWithUnions.symbols | 144 +++++++++++++ .../excessPropertyCheckWithUnions.types | 196 ++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 tests/baselines/reference/excessPropertyCheckWithUnions.symbols create mode 100644 tests/baselines/reference/excessPropertyCheckWithUnions.types diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols new file mode 100644 index 0000000000000..332166e396c8f --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols @@ -0,0 +1,144 @@ +=== tests/cases/compiler/excessPropertyCheckWithUnions.ts === +type ADT = { +>ADT : Symbol(ADT, Decl(excessPropertyCheckWithUnions.ts, 0, 0)) + + tag: "A", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 0, 12)) + + a1: string +>a1 : Symbol(a1, Decl(excessPropertyCheckWithUnions.ts, 1, 13)) + +} | { + tag: "D", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 3, 5)) + + d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 +>d20 : Symbol(d20, Decl(excessPropertyCheckWithUnions.ts, 4, 13)) + +} | { + tag: "T", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 6, 5)) +} +let wrong: ADT = { tag: "T", a1: "extra" } +>wrong : Symbol(wrong, Decl(excessPropertyCheckWithUnions.ts, 9, 3)) +>ADT : Symbol(ADT, Decl(excessPropertyCheckWithUnions.ts, 0, 0)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 9, 18)) +>a1 : Symbol(a1, Decl(excessPropertyCheckWithUnions.ts, 9, 28)) + +wrong = { tag: "A", d20: 12 } +>wrong : Symbol(wrong, Decl(excessPropertyCheckWithUnions.ts, 9, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 10, 9)) +>d20 : Symbol(d20, Decl(excessPropertyCheckWithUnions.ts, 10, 19)) + +wrong = { tag: "D" } +>wrong : Symbol(wrong, Decl(excessPropertyCheckWithUnions.ts, 9, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 11, 9)) + +type Ambiguous = { +>Ambiguous : Symbol(Ambiguous, Decl(excessPropertyCheckWithUnions.ts, 11, 20)) + + tag: "A", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 13, 18)) + + x: string +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 14, 13)) + +} | { + tag: "A", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 16, 5)) + + y: number +>y : Symbol(y, Decl(excessPropertyCheckWithUnions.ts, 17, 13)) + +} | { + tag: "B", +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 19, 5)) + + z: boolean +>z : Symbol(z, Decl(excessPropertyCheckWithUnions.ts, 20, 13)) + +} | { + tag: "C" +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 22, 5)) +} +let amb: Ambiguous +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>Ambiguous : Symbol(Ambiguous, Decl(excessPropertyCheckWithUnions.ts, 11, 20)) + +// no error for ambiguous tag, even when it could satisfy both constituents at once +amb = { tag: "A", x: "hi" } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 27, 7)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 27, 17)) + +amb = { tag: "A", y: 12 } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 28, 7)) +>y : Symbol(y, Decl(excessPropertyCheckWithUnions.ts, 28, 17)) + +amb = { tag: "A", x: "hi", y: 12 } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 29, 7)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 29, 17)) +>y : Symbol(y, Decl(excessPropertyCheckWithUnions.ts, 29, 26)) + +// correctly error on excess property 'extra', even when ambiguous +amb = { tag: "A", x: "hi", extra: 12 } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 32, 7)) +>x : Symbol(x, Decl(excessPropertyCheckWithUnions.ts, 32, 17)) +>extra : Symbol(extra, Decl(excessPropertyCheckWithUnions.ts, 32, 26)) + +amb = { tag: "A", y: 12, extra: 12 } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 33, 7)) +>y : Symbol(y, Decl(excessPropertyCheckWithUnions.ts, 33, 17)) +>extra : Symbol(extra, Decl(excessPropertyCheckWithUnions.ts, 33, 24)) + +// assignability errors still work. +// But note that the error for `z: true` is the fallback one of reporting on +// the last constituent since assignability error reporting can't find a single best discriminant either. +amb = { tag: "A" } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 38, 7)) + +amb = { tag: "A", z: true } +>amb : Symbol(amb, Decl(excessPropertyCheckWithUnions.ts, 25, 3)) +>tag : Symbol(tag, Decl(excessPropertyCheckWithUnions.ts, 39, 7)) +>z : Symbol(z, Decl(excessPropertyCheckWithUnions.ts, 39, 17)) + +type Overlapping = +>Overlapping : Symbol(Overlapping, Decl(excessPropertyCheckWithUnions.ts, 39, 27)) + + | { a: 1, b: 1, first: string } +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 42, 7)) +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 42, 13)) +>first : Symbol(first, Decl(excessPropertyCheckWithUnions.ts, 42, 19)) + + | { a: 2, second: string } +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 43, 7)) +>second : Symbol(second, Decl(excessPropertyCheckWithUnions.ts, 43, 13)) + + | { b: 3, third: string } +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 44, 7)) +>third : Symbol(third, Decl(excessPropertyCheckWithUnions.ts, 44, 13)) + +let over: Overlapping +>over : Symbol(over, Decl(excessPropertyCheckWithUnions.ts, 45, 3)) +>Overlapping : Symbol(Overlapping, Decl(excessPropertyCheckWithUnions.ts, 39, 27)) + +// these two are not reported because there are two discriminant properties +over = { a: 1, b: 1, first: "ok", second: "error" } +>over : Symbol(over, Decl(excessPropertyCheckWithUnions.ts, 45, 3)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 48, 8)) +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 48, 14)) +>first : Symbol(first, Decl(excessPropertyCheckWithUnions.ts, 48, 20)) +>second : Symbol(second, Decl(excessPropertyCheckWithUnions.ts, 48, 33)) + +over = { a: 1, b: 1, first: "ok", third: "error" } +>over : Symbol(over, Decl(excessPropertyCheckWithUnions.ts, 45, 3)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 49, 8)) +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 49, 14)) +>first : Symbol(first, Decl(excessPropertyCheckWithUnions.ts, 49, 20)) +>third : Symbol(third, Decl(excessPropertyCheckWithUnions.ts, 49, 33)) + diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.types b/tests/baselines/reference/excessPropertyCheckWithUnions.types new file mode 100644 index 0000000000000..1d6bdd32eb269 --- /dev/null +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.types @@ -0,0 +1,196 @@ +=== tests/cases/compiler/excessPropertyCheckWithUnions.ts === +type ADT = { +>ADT : ADT + + tag: "A", +>tag : "A" + + a1: string +>a1 : string + +} | { + tag: "D", +>tag : "D" + + d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 +>d20 : 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 + +} | { + tag: "T", +>tag : "T" +} +let wrong: ADT = { tag: "T", a1: "extra" } +>wrong : ADT +>ADT : ADT +>{ tag: "T", a1: "extra" } : { tag: "T"; a1: string; } +>tag : string +>"T" : "T" +>a1 : string +>"extra" : "extra" + +wrong = { tag: "A", d20: 12 } +>wrong = { tag: "A", d20: 12 } : { tag: "A"; d20: 12; } +>wrong : ADT +>{ tag: "A", d20: 12 } : { tag: "A"; d20: 12; } +>tag : string +>"A" : "A" +>d20 : number +>12 : 12 + +wrong = { tag: "D" } +>wrong = { tag: "D" } : { tag: "D"; } +>wrong : ADT +>{ tag: "D" } : { tag: "D"; } +>tag : string +>"D" : "D" + +type Ambiguous = { +>Ambiguous : Ambiguous + + tag: "A", +>tag : "A" + + x: string +>x : string + +} | { + tag: "A", +>tag : "A" + + y: number +>y : number + +} | { + tag: "B", +>tag : "B" + + z: boolean +>z : boolean + +} | { + tag: "C" +>tag : "C" +} +let amb: Ambiguous +>amb : Ambiguous +>Ambiguous : Ambiguous + +// no error for ambiguous tag, even when it could satisfy both constituents at once +amb = { tag: "A", x: "hi" } +>amb = { tag: "A", x: "hi" } : { tag: "A"; x: string; } +>amb : Ambiguous +>{ tag: "A", x: "hi" } : { tag: "A"; x: string; } +>tag : string +>"A" : "A" +>x : string +>"hi" : "hi" + +amb = { tag: "A", y: 12 } +>amb = { tag: "A", y: 12 } : { tag: "A"; y: number; } +>amb : Ambiguous +>{ tag: "A", y: 12 } : { tag: "A"; y: number; } +>tag : string +>"A" : "A" +>y : number +>12 : 12 + +amb = { tag: "A", x: "hi", y: 12 } +>amb = { tag: "A", x: "hi", y: 12 } : { tag: "A"; x: string; y: number; } +>amb : Ambiguous +>{ tag: "A", x: "hi", y: 12 } : { tag: "A"; x: string; y: number; } +>tag : string +>"A" : "A" +>x : string +>"hi" : "hi" +>y : number +>12 : 12 + +// correctly error on excess property 'extra', even when ambiguous +amb = { tag: "A", x: "hi", extra: 12 } +>amb = { tag: "A", x: "hi", extra: 12 } : { tag: "A"; x: string; extra: number; } +>amb : Ambiguous +>{ tag: "A", x: "hi", extra: 12 } : { tag: "A"; x: string; extra: number; } +>tag : string +>"A" : "A" +>x : string +>"hi" : "hi" +>extra : number +>12 : 12 + +amb = { tag: "A", y: 12, extra: 12 } +>amb = { tag: "A", y: 12, extra: 12 } : { tag: "A"; y: number; extra: number; } +>amb : Ambiguous +>{ tag: "A", y: 12, extra: 12 } : { tag: "A"; y: number; extra: number; } +>tag : string +>"A" : "A" +>y : number +>12 : 12 +>extra : number +>12 : 12 + +// assignability errors still work. +// But note that the error for `z: true` is the fallback one of reporting on +// the last constituent since assignability error reporting can't find a single best discriminant either. +amb = { tag: "A" } +>amb = { tag: "A" } : { tag: "A"; } +>amb : Ambiguous +>{ tag: "A" } : { tag: "A"; } +>tag : string +>"A" : "A" + +amb = { tag: "A", z: true } +>amb = { tag: "A", z: true } : { tag: "A"; z: true; } +>amb : Ambiguous +>{ tag: "A", z: true } : { tag: "A"; z: true; } +>tag : string +>"A" : "A" +>z : boolean +>true : true + +type Overlapping = +>Overlapping : Overlapping + + | { a: 1, b: 1, first: string } +>a : 1 +>b : 1 +>first : string + + | { a: 2, second: string } +>a : 2 +>second : string + + | { b: 3, third: string } +>b : 3 +>third : string + +let over: Overlapping +>over : Overlapping +>Overlapping : Overlapping + +// these two are not reported because there are two discriminant properties +over = { a: 1, b: 1, first: "ok", second: "error" } +>over = { a: 1, b: 1, first: "ok", second: "error" } : { a: 1; b: 1; first: string; second: string; } +>over : Overlapping +>{ a: 1, b: 1, first: "ok", second: "error" } : { a: 1; b: 1; first: string; second: string; } +>a : number +>1 : 1 +>b : number +>1 : 1 +>first : string +>"ok" : "ok" +>second : string +>"error" : "error" + +over = { a: 1, b: 1, first: "ok", third: "error" } +>over = { a: 1, b: 1, first: "ok", third: "error" } : { a: 1; b: 1; first: string; third: string; } +>over : Overlapping +>{ a: 1, b: 1, first: "ok", third: "error" } : { a: 1; b: 1; first: string; third: string; } +>a : number +>1 : 1 +>b : number +>1 : 1 +>first : string +>"ok" : "ok" +>third : string +>"error" : "error" + From 2facead886b2850df151dca9cf2852f0e68f800c Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 5 Oct 2017 09:54:21 -0700 Subject: [PATCH 047/246] Update tests after the merge from master --- src/harness/unittests/tsserverProjectSystem.ts | 11 +++++------ src/harness/virtualFileSystemWithWatch.ts | 12 ++++++++---- tests/baselines/reference/api/tsserverlibrary.d.ts | 7 +------ 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 06e2beeaaa6cf..e594093605a5d 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -352,8 +352,6 @@ namespace ts.projectSystem { verifyDiagnostics(actual, []); } - const typeRootFromTsserverLocation = "/node_modules/@types"; - export function getTypeRootsFromLocation(currentDirectory: string) { currentDirectory = normalizePath(currentDirectory); const result: string[] = []; @@ -401,7 +399,7 @@ namespace ts.projectSystem { const configFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]); checkWatchedFiles(host, configFiles.concat(libFile.path, moduleFile.path)); checkWatchedDirectories(host, [], /*recursive*/ false); - checkWatchedDirectories(host, ["/a/b/c", typeRootFromTsserverLocation], /*recursive*/ true); + checkWatchedDirectories(host, ["/a/b/c", ...getTypeRootsFromLocation(getDirectoryPath(appFile.path))], /*recursive*/ true); }); it("can handle tsconfig file name with difference casing", () => { @@ -4331,7 +4329,7 @@ namespace ts.projectSystem { function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: Map) { const calledMap = calledMaps[callback]; - assert.equal(calledMap.size, expectedKeys.size, `${callback}: incorrect size of map: Actual keys: ${arrayFrom(calledMap.keys())} Expected: ${arrayFrom(expectedKeys.keys())}`); + ts.TestFSWithWatch.verifyMapSize(callback, calledMap, arrayFrom(expectedKeys.keys())); expectedKeys.forEach((called, name) => { assert.isTrue(calledMap.has(name), `${callback} is expected to contain ${name}, actual keys: ${arrayFrom(calledMap.keys())}`); assert.equal(calledMap.get(name).length, called, `${callback} is expected to be called ${called} times with ${name}. Actual entry: ${calledMap.get(name)}`); @@ -4413,6 +4411,7 @@ namespace ts.projectSystem { } const f2Lookups = getLocationsForModuleLookup("f2"); callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1); + const typeRootLocations = getTypeRootsFromLocation(getDirectoryPath(root.path)); const f2DirLookups = getLocationsForDirectoryLookup(); callsTrackingHost.verifyCalledOnEachEntry(CalledMapsWithSingleArg.directoryExists, f2DirLookups); callsTrackingHost.verifyNoCall(CalledMapsWithSingleArg.getDirectories); @@ -4423,7 +4422,7 @@ namespace ts.projectSystem { verifyImportedDiagnostics(); const f1Lookups = f2Lookups.map(s => s.replace("f2", "f1")); f1Lookups.length = f1Lookups.indexOf(imported.path) + 1; - const f1DirLookups = ["/c/d", "/c", typeRootFromTsserverLocation]; + const f1DirLookups = ["/c/d", "/c", ...typeRootLocations]; vertifyF1Lookups(); // setting compiler options discards module resolution cache @@ -4475,7 +4474,7 @@ namespace ts.projectSystem { function getLocationsForDirectoryLookup() { const result = createMap(); // Type root - result.set(typeRootFromTsserverLocation, 1); + typeRootLocations.forEach(location => result.set(location, 1)); forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { // To resolve modules result.set(ancestor, 2); diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index c16f57235e412..ff782bbf7d2ed 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -95,7 +95,7 @@ namespace ts.TestFSWithWatch { } } - function getDiffInKeys(map: Map, expectedKeys: ReadonlyArray) { + function getDiffInKeys(map: Map, expectedKeys: ReadonlyArray) { if (map.size === expectedKeys.length) { return ""; } @@ -122,8 +122,12 @@ namespace ts.TestFSWithWatch { return `\n\nNotInActual: ${notInActual}\nDuplicates: ${duplicates}\nInActualButNotInExpected: ${inActualNotExpected}`; } - function checkMapKeys(caption: string, map: Map, expectedKeys: ReadonlyArray) { + export function verifyMapSize(caption: string, map: Map, expectedKeys: ReadonlyArray) { assert.equal(map.size, expectedKeys.length, `${caption}: incorrect size of map: Actual keys: ${arrayFrom(map.keys())} Expected: ${expectedKeys}${getDiffInKeys(map, expectedKeys)}`); + } + + function checkMapKeys(caption: string, map: Map, expectedKeys: ReadonlyArray) { + verifyMapSize(caption, map, expectedKeys); for (const name of expectedKeys) { assert.isTrue(map.has(name), `${caption} is expected to contain ${name}, actual keys: ${arrayFrom(map.keys())}`); } @@ -548,7 +552,7 @@ namespace ts.TestFSWithWatch { const folder = this.toFolder(directoryName); // base folder has to be present - const base = getDirectoryPath(folder.fullPath); + const base = getDirectoryPath(folder.path); const baseFolder = this.fs.get(base) as Folder; Debug.assert(isFolder(baseFolder)); @@ -560,7 +564,7 @@ namespace ts.TestFSWithWatch { const file = this.toFile({ path, content }); // base folder has to be present - const base = getDirectoryPath(file.fullPath); + const base = getDirectoryPath(file.path); const folder = this.fs.get(base) as Folder; Debug.assert(isFolder(folder)); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3bb2ed1167488..713188e9da8f5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7131,7 +7131,6 @@ declare namespace ts.server { enableLanguageService(): void; disableLanguageService(): void; getProjectName(): string; - abstract getProjectRootPath(): string | undefined; abstract getTypeAcquisition(): TypeAcquisition; getExternalFiles(): SortedReadonlyArray; getSourceFile(path: Path): SourceFile; @@ -7184,7 +7183,6 @@ declare namespace ts.server { addRoot(info: ScriptInfo): void; removeRoot(info: ScriptInfo): void; isProjectWithSingleRoot(): boolean; - getProjectRootPath(): string; close(): void; getTypeAcquisition(): TypeAcquisition; } @@ -7211,7 +7209,6 @@ declare namespace ts.server { enablePlugins(): void; private enablePlugin(pluginConfigEntry, searchPaths); private enableProxy(pluginModuleFactory, configEntry); - getProjectRootPath(): string; /** * Get the errors that dont have any file name associated */ @@ -7237,11 +7234,9 @@ declare namespace ts.server { class ExternalProject extends Project { externalProjectName: string; compileOnSaveEnabled: boolean; - private readonly projectFilePath; excludedFiles: ReadonlyArray; private typeAcquisition; getExcludedFiles(): ReadonlyArray; - getProjectRootPath(): string; getTypeAcquisition(): TypeAcquisition; setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void; } @@ -7519,7 +7514,7 @@ declare namespace ts.server { private updateNonInferredProject(project, newUncheckedFiles, propertyReader, newOptions, newTypeAcquisition, compileOnSave); private getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath); private getOrCreateSingleInferredProjectIfEnabled(); - private createInferredProject(rootDirectoryForResolution, isSingleInferredProject?, projectRootPath?); + private createInferredProject(currentDirectory, isSingleInferredProject?, projectRootPath?); getScriptInfo(uncheckedFileName: string): ScriptInfo; private watchClosedScriptInfo(info); private stopWatchingScriptInfo(info); From 32d705dbb53b48d2d473547d7ec566d3df818df8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 5 Oct 2017 11:29:00 -0700 Subject: [PATCH 048/246] Fine tune logging so that only triggers in watch are logged in normal logging vs verbose --- src/compiler/watch.ts | 8 ++++---- src/compiler/watchUtilities.ts | 31 +++++++++++++++++++++++++------ src/server/editorServices.ts | 5 +++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 779efb62c4663..2ab3ccc5ce65d 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -249,10 +249,10 @@ namespace ts { let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed const loggingEnabled = compilerOptions.diagnostics || compilerOptions.extendedDiagnostics; - const writeLog: (s: string) => void = loggingEnabled ? s => system.write(s) : noop; - const watchFile = loggingEnabled ? ts.addFileWatcherWithLogging : ts.addFileWatcher; - const watchFilePath = loggingEnabled ? ts.addFilePathWatcherWithLogging : ts.addFilePathWatcher; - const watchDirectoryWorker = loggingEnabled ? ts.addDirectoryWatcherWithLogging : ts.addDirectoryWatcher; + const writeLog: (s: string) => void = loggingEnabled ? s => { system.write(s); system.write(system.newLine); } : noop; + const watchFile = compilerOptions.extendedDiagnostics ? ts.addFileWatcherWithLogging : loggingEnabled ? ts.addFileWatcherWithOnlyTriggerLogging : ts.addFileWatcher; + const watchFilePath = compilerOptions.extendedDiagnostics ? ts.addFilePathWatcherWithLogging : ts.addFilePathWatcher; + const watchDirectoryWorker = compilerOptions.extendedDiagnostics ? ts.addDirectoryWatcherWithLogging : ts.addDirectoryWatcher; watchingHost = watchingHost || createWatchingSystemHost(compilerOptions.pretty); const { system, parseConfigFile, reportDiagnostic, reportWatchDiagnostic, beforeCompile, afterCompile } = watchingHost; diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index de4152939545e..26bf689401a8c 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -82,7 +82,12 @@ namespace ts { export function addFileWatcherWithLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher { const watcherCaption = `FileWatcher:: `; - return createWatcherWithLogging(addFileWatcher, watcherCaption, log, host, file, cb); + return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb); + } + + export function addFileWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FileWatcherCallback, log: (s: string) => void): FileWatcher { + const watcherCaption = `FileWatcher:: `; + return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb); } export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void; @@ -92,7 +97,12 @@ namespace ts { export function addFilePathWatcherWithLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher { const watcherCaption = `FileWatcher:: `; - return createWatcherWithLogging(addFileWatcher, watcherCaption, log, host, file, cb, path); + return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, file, cb, path); + } + + export function addFilePathWatcherWithOnlyTriggerLogging(host: System, file: string, cb: FilePathWatcherCallback, path: Path, log: (s: string) => void): FileWatcher { + const watcherCaption = `FileWatcher:: `; + return createWatcherWithLogging(addFileWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, file, cb, path); } export function addDirectoryWatcher(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher { @@ -102,14 +112,21 @@ namespace ts { export function addDirectoryWatcherWithLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher { const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `; - return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, host, directory, cb, flags); + return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ false, host, directory, cb, flags); + } + + export function addDirectoryWatcherWithOnlyTriggerLogging(host: System, directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags, log: (s: string) => void): FileWatcher { + const watcherCaption = `DirectoryWatcher ${(flags & WatchDirectoryFlags.Recursive) !== 0 ? "recursive" : ""}:: `; + return createWatcherWithLogging(addDirectoryWatcher, watcherCaption, log, /*logOnlyTrigger*/ true, host, directory, cb, flags); } type WatchCallback = (fileName: string, cbOptional1?: T, optional?: U) => void; type AddWatch = (host: System, file: string, cb: WatchCallback, optional?: U) => FileWatcher; - function createWatcherWithLogging(addWatch: AddWatch, watcherCaption: string, log: (s: string) => void, host: System, file: string, cb: WatchCallback, optional?: U): FileWatcher { + function createWatcherWithLogging(addWatch: AddWatch, watcherCaption: string, log: (s: string) => void, logOnlyTrigger: boolean, host: System, file: string, cb: WatchCallback, optional?: U): FileWatcher { const info = `PathInfo: ${file}`; - log(`${watcherCaption}Added: ${info}`); + if (!logOnlyTrigger) { + log(`${watcherCaption}Added: ${info}`); + } const watcher = addWatch(host, file, (fileName, cbOptional1?) => { const optionalInfo = cbOptional1 !== undefined ? ` ${cbOptional1}` : ""; log(`${watcherCaption}Trigger: ${fileName}${optionalInfo} ${info}`); @@ -120,7 +137,9 @@ namespace ts { }, optional); return { close: () => { - log(`${watcherCaption}Close: ${info}`); + if (!logOnlyTrigger) { + log(`${watcherCaption}Close: ${info}`); + } watcher.close(); } }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 25a285929bef2..2916fb60c5734 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -431,6 +431,11 @@ namespace ts.server { this.watchFilePath = (host, file, cb, path, watchType, project) => ts.addFilePathWatcherWithLogging(host, file, cb, path, this.createWatcherLog(watchType, project)); this.watchDirectory = (host, dir, cb, flags, watchType, project) => ts.addDirectoryWatcherWithLogging(host, dir, cb, flags, this.createWatcherLog(watchType, project)); } + else if (this.logger.loggingEnabled()) { + this.watchFile = (host, file, cb, watchType, project) => ts.addFileWatcherWithOnlyTriggerLogging(host, file, cb, this.createWatcherLog(watchType, project)); + this.watchFilePath = (host, file, cb, path, watchType, project) => ts.addFilePathWatcherWithOnlyTriggerLogging(host, file, cb, path, this.createWatcherLog(watchType, project)); + this.watchDirectory = (host, dir, cb, flags, watchType, project) => ts.addDirectoryWatcherWithOnlyTriggerLogging(host, dir, cb, flags, this.createWatcherLog(watchType, project)); + } else { this.watchFile = ts.addFileWatcher; this.watchFilePath = ts.addFilePathWatcher; From e5eccf0a22104f2242cebbf636e6ad2336d328f1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 30 Sep 2017 00:58:09 -0700 Subject: [PATCH 049/246] Added test. --- .../codeFixAddForgottenDecoratorCall01.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/cases/fourslash/codeFixAddForgottenDecoratorCall01.ts diff --git a/tests/cases/fourslash/codeFixAddForgottenDecoratorCall01.ts b/tests/cases/fourslash/codeFixAddForgottenDecoratorCall01.ts new file mode 100644 index 0000000000000..17ae7f626f069 --- /dev/null +++ b/tests/cases/fourslash/codeFixAddForgottenDecoratorCall01.ts @@ -0,0 +1,14 @@ +/// + +////declare function foo(): (...args: any[]) => void; +////class C { +//// [|@foo|] +//// bar() { +//// +//// } +////} + +verify.codeFix({ + description: "Call decorator expression.", + newRangeContent: `@foo()` +}); From ea2021dd3e49a016dac58de326601e24c02f8a09 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 30 Sep 2017 00:58:46 -0700 Subject: [PATCH 050/246] Create fix for uninvoked decorators. --- src/compiler/diagnosticMessages.json | 4 ++++ .../addMissingInvocationForDecorator.ts | 20 +++++++++++++++++++ src/services/codefixes/fixes.ts | 1 + 3 files changed, 25 insertions(+) create mode 100644 src/services/codefixes/addMissingInvocationForDecorator.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 17c2366082035..f3d6d4fcc4706 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3709,6 +3709,10 @@ "category": "Message", "code": 90027 }, + "Call decorator expression.": { + "category": "Message", + "code": 90028 + }, "Convert function to an ES2015 class": { "category": "Message", diff --git a/src/services/codefixes/addMissingInvocationForDecorator.ts b/src/services/codefixes/addMissingInvocationForDecorator.ts new file mode 100644 index 0000000000000..7f17aab6db2a8 --- /dev/null +++ b/src/services/codefixes/addMissingInvocationForDecorator.ts @@ -0,0 +1,20 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0.code], + getCodeActions: (context: CodeFixContext) => { + const sourceFile = context.sourceFile; + const token = getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); + const decorator = getAncestor(token, SyntaxKind.Decorator) as Decorator; + Debug.assert(!!decorator, "Expected position to be owned by a decorator."); + const replacement = createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); + const changeTracker = textChanges.ChangeTracker.fromContext(context); + changeTracker.replaceNode(sourceFile, decorator.expression, replacement); + + return [{ + description: getLocaleSpecificMessage(Diagnostics.Call_decorator_expression), + changes: changeTracker.getChanges() + }]; + } + }); +} diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index 9bc80cad69117..b024dfae7cd82 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -1,3 +1,4 @@ +/// /// /// /// From c3d1b027dcf27520a2a2e64a0e95aa64ea62505f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 5 Oct 2017 13:18:38 -0700 Subject: [PATCH 051/246] Don't use callback parameter code path when strictly checking functions --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58248a8a9ee75..5ea946aa89888 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8540,7 +8540,7 @@ namespace ts { } const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; - const strictVariance = strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && + const strictVariance = !checkAsCallback && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; let result = Ternary.True; @@ -8579,7 +8579,7 @@ namespace ts { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const callbacks = sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate && + const callbacks = !strictVariance && sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate && (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); const related = callbacks ? compareSignaturesRelated(targetSig, sourceSig, /*checkAsCallback*/ true, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : From 0dc1c77f231762079ba106ea7fd828355c2a8852 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 5 Oct 2017 13:18:49 -0700 Subject: [PATCH 052/246] Accept new baselines --- .../strictFunctionTypesErrors.errors.txt | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 2827983bd5ae1..661ad437ed29d 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -40,26 +40,22 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(58,1): error TS2322: Type 'Fun Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(61,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, Object>'. Types of parameters 'x' and 'x' are incompatible. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. + Type 'Func' is not assignable to type 'Func'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(62,1): error TS2322: Type 'Func, string>' is not assignable to type 'Func, Object>'. Types of parameters 'x' and 'x' are incompatible. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. + Type 'Func' is not assignable to type 'Func'. tests/cases/compiler/strictFunctionTypesErrors.ts(65,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. Types of parameters 'x' and 'x' are incompatible. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. + Type 'Func' is not assignable to type 'Func'. tests/cases/compiler/strictFunctionTypesErrors.ts(66,1): error TS2322: Type 'Func, string>' is not assignable to type 'Func, string>'. Types of parameters 'x' and 'x' are incompatible. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. + Type 'Func' is not assignable to type 'Func'. tests/cases/compiler/strictFunctionTypesErrors.ts(67,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(74,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Type 'Func' is not assignable to type 'Func'. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(75,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Types of parameters 'x' and 'x' are incompatible. Type 'Object' is not assignable to type 'string'. @@ -210,28 +206,26 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Cr ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, Object>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. +!!! error TS2322: Type 'Func' is not assignable to type 'Func'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. h3 = h2; // Error ~~ !!! error TS2322: Type 'Func, string>' is not assignable to type 'Func, Object>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. +!!! error TS2322: Type 'Func' is not assignable to type 'Func'. h3 = h4; // Ok h4 = h1; // Error ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. +!!! error TS2322: Type 'Func' is not assignable to type 'Func'. h4 = h2; // Error ~~ !!! error TS2322: Type 'Func, string>' is not assignable to type 'Func, string>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. +!!! error TS2322: Type 'Func' is not assignable to type 'Func'. h4 = h3; // Error ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. @@ -246,8 +240,6 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Cr ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. !!! error TS2322: Type 'Func' is not assignable to type 'Func'. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. i1 = i3; // Error ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. From aae7572c4869dd5a62acd4311e8f7fdefd1f05f6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 5 Oct 2017 13:25:23 -0700 Subject: [PATCH 053/246] Add test --- .../strictFunctionTypesErrors.errors.txt | 29 ++++++++++++++++++- .../reference/strictFunctionTypesErrors.js | 9 ++++++ .../strictFunctionTypesErrors.symbols | 24 +++++++++++++++ .../reference/strictFunctionTypesErrors.types | 26 +++++++++++++++++ .../compiler/strictFunctionTypesErrors.ts | 7 +++++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 661ad437ed29d..6a8204fb1478e 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -83,9 +83,18 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(126,1): error TS2322: Type 'Cr tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Crate' is not assignable to type 'Crate'. Types of property 'item' are incompatible. Type 'Animal' is not assignable to type 'Dog'. +tests/cases/compiler/strictFunctionTypesErrors.ts(133,1): error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'. + Types of parameters 'f' and 'f' are incompatible. + Type '(x: Animal) => Animal' is not assignable to type '(x: Dog) => Dog'. + Type 'Animal' is not assignable to type 'Dog'. +tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'. + Types of parameters 'f' and 'f' are incompatible. + Type '(x: Dog) => Dog' is not assignable to type '(x: Animal) => Animal'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Animal' is not assignable to type 'Dog'. -==== tests/cases/compiler/strictFunctionTypesErrors.ts (31 errors) ==== +==== tests/cases/compiler/strictFunctionTypesErrors.ts (33 errors) ==== export {} @@ -329,4 +338,22 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Cr !!! error TS2322: Type 'Crate' is not assignable to type 'Crate'. !!! error TS2322: Types of property 'item' are incompatible. !!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. + + // Verify that callback parameters are strictly checked + + declare let fc1: (f: (x: Animal) => Animal) => void; + declare let fc2: (f: (x: Dog) => Dog) => void; + fc1 = fc2; // Error + ~~~ +!!! error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'. +!!! error TS2322: Types of parameters 'f' and 'f' are incompatible. +!!! error TS2322: Type '(x: Animal) => Animal' is not assignable to type '(x: Dog) => Dog'. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. + fc2 = fc1; // Error + ~~~ +!!! error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'. +!!! error TS2322: Types of parameters 'f' and 'f' are incompatible. +!!! error TS2322: Type '(x: Dog) => Dog' is not assignable to type '(x: Animal) => Animal'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. \ No newline at end of file diff --git a/tests/baselines/reference/strictFunctionTypesErrors.js b/tests/baselines/reference/strictFunctionTypesErrors.js index 2be598f0ef9c3..8e338fa030d0d 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.js +++ b/tests/baselines/reference/strictFunctionTypesErrors.js @@ -126,6 +126,13 @@ declare let dogCrate: Crate; animalCrate = dogCrate; // Error dogCrate = animalCrate; // Error + +// Verify that callback parameters are strictly checked + +declare let fc1: (f: (x: Animal) => Animal) => void; +declare let fc2: (f: (x: Dog) => Dog) => void; +fc1 = fc2; // Error +fc2 = fc1; // Error //// [strictFunctionTypesErrors.js] @@ -186,3 +193,5 @@ dogComparer2 = animalComparer2; // Ok // Errors below should elaborate the reason for invariance animalCrate = dogCrate; // Error dogCrate = animalCrate; // Error +fc1 = fc2; // Error +fc2 = fc1; // Error diff --git a/tests/baselines/reference/strictFunctionTypesErrors.symbols b/tests/baselines/reference/strictFunctionTypesErrors.symbols index 30faf83d87e25..fd28775c5e13d 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.symbols +++ b/tests/baselines/reference/strictFunctionTypesErrors.symbols @@ -400,3 +400,27 @@ dogCrate = animalCrate; // Error >dogCrate : Symbol(dogCrate, Decl(strictFunctionTypesErrors.ts, 121, 11)) >animalCrate : Symbol(animalCrate, Decl(strictFunctionTypesErrors.ts, 120, 11)) +// Verify that callback parameters are strictly checked + +declare let fc1: (f: (x: Animal) => Animal) => void; +>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11)) +>f : Symbol(f, Decl(strictFunctionTypesErrors.ts, 130, 18)) +>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 130, 22)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) + +declare let fc2: (f: (x: Dog) => Dog) => void; +>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11)) +>f : Symbol(f, Decl(strictFunctionTypesErrors.ts, 131, 18)) +>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 131, 22)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) + +fc1 = fc2; // Error +>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11)) +>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11)) + +fc2 = fc1; // Error +>fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11)) +>fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11)) + diff --git a/tests/baselines/reference/strictFunctionTypesErrors.types b/tests/baselines/reference/strictFunctionTypesErrors.types index e4372d4b8fa20..45deeebababee 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.types +++ b/tests/baselines/reference/strictFunctionTypesErrors.types @@ -454,3 +454,29 @@ dogCrate = animalCrate; // Error >dogCrate : Crate >animalCrate : Crate +// Verify that callback parameters are strictly checked + +declare let fc1: (f: (x: Animal) => Animal) => void; +>fc1 : (f: (x: Animal) => Animal) => void +>f : (x: Animal) => Animal +>x : Animal +>Animal : Animal +>Animal : Animal + +declare let fc2: (f: (x: Dog) => Dog) => void; +>fc2 : (f: (x: Dog) => Dog) => void +>f : (x: Dog) => Dog +>x : Dog +>Dog : Dog +>Dog : Dog + +fc1 = fc2; // Error +>fc1 = fc2 : (f: (x: Dog) => Dog) => void +>fc1 : (f: (x: Animal) => Animal) => void +>fc2 : (f: (x: Dog) => Dog) => void + +fc2 = fc1; // Error +>fc2 = fc1 : (f: (x: Animal) => Animal) => void +>fc2 : (f: (x: Dog) => Dog) => void +>fc1 : (f: (x: Animal) => Animal) => void + diff --git a/tests/cases/compiler/strictFunctionTypesErrors.ts b/tests/cases/compiler/strictFunctionTypesErrors.ts index fbf1c0fa6da92..95598d9d44425 100644 --- a/tests/cases/compiler/strictFunctionTypesErrors.ts +++ b/tests/cases/compiler/strictFunctionTypesErrors.ts @@ -126,3 +126,10 @@ declare let dogCrate: Crate; animalCrate = dogCrate; // Error dogCrate = animalCrate; // Error + +// Verify that callback parameters are strictly checked + +declare let fc1: (f: (x: Animal) => Animal) => void; +declare let fc2: (f: (x: Dog) => Dog) => void; +fc1 = fc2; // Error +fc2 = fc1; // Error From a5e184118088342db9db79c49f6cb95e53f63b72 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 5 Oct 2017 15:37:47 -0700 Subject: [PATCH 054/246] Handle undefined in getSynthesizedClone --- src/compiler/factory.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 968144c0fc771..fe183c5e8060c 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -47,10 +47,15 @@ namespace ts { * Creates a shallow, memberwise clone of a node with no source map location. */ /* @internal */ - export function getSynthesizedClone(node: T | undefined): T { + export function getSynthesizedClone(node: T | undefined): T | undefined { // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). + + if (node === undefined) { + return undefined; + } + const clone = createSynthesizedNode(node.kind); clone.flags |= node.flags; setOriginalNode(clone, node); From 380b8df13f3ff9deaf36c6a7aa3ae0c7fd4ce960 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 5 Oct 2017 15:38:02 -0700 Subject: [PATCH 055/246] Introduce getSynthesizedDeepClone --- src/compiler/factory.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index fe183c5e8060c..84c28abe1a51e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -71,6 +71,15 @@ namespace ts { return clone; } + /** + * Creates a deep, memberwise clone of a node with no source map location. + */ + export function getSynthesizedDeepClone(node: T | undefined): T | undefined { + return node + ? getSynthesizedClone(visitEachChild(node, child => getSynthesizedDeepClone(child), nullTransformationContext)) + : undefined; + } + // Literals export function createLiteral(value: string): StringLiteral; From ad148dbc8800da4bbd2863a68f6f6617ee776a7a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 5 Oct 2017 15:46:14 -0700 Subject: [PATCH 056/246] Use deep cloning, rather than thunking for repeated substitution Replaces b244cd4fb47 --- src/services/refactors/extractSymbol.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 0e2f5ebfe3cd7..0176841e34618 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1064,7 +1064,7 @@ namespace ts.refactor.extractSymbol { } } - function transformFunctionBody(body: Node, writes: ReadonlyArray, substitutions: ReadonlyMap<() => Node>, hasReturn: boolean): { body: Block, returnValueProperty: string } { + function transformFunctionBody(body: Node, writes: ReadonlyArray, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block, returnValueProperty: string } { if (isBlock(body) && !writes && substitutions.size === 0) { // already block, no writes to propagate back, no substitutions - can use node as is return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; @@ -1112,21 +1112,21 @@ namespace ts.refactor.extractSymbol { const oldIgnoreReturns = ignoreReturns; ignoreReturns = ignoreReturns || isFunctionLikeDeclaration(node) || isClassLike(node); const substitution = substitutions.get(getNodeId(node).toString()); - const result = substitution ? substitution() : visitEachChild(node, visitor, nullTransformationContext); + const result = substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); ignoreReturns = oldIgnoreReturns; return result; } } } - function transformConstantInitializer(initializer: Expression, substitutions: ReadonlyMap<() => Node>): Expression { + function transformConstantInitializer(initializer: Expression, substitutions: ReadonlyMap): Expression { return substitutions.size ? visitor(initializer) as Expression : initializer; function visitor(node: Node): VisitResult { const substitution = substitutions.get(getNodeId(node).toString()); - return substitution ? substitution() : visitEachChild(node, visitor, nullTransformationContext); + return substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); } } @@ -1255,7 +1255,7 @@ namespace ts.refactor.extractSymbol { interface ScopeUsages { readonly usages: Map; readonly typeParameterUsages: Map; // Key is type ID - readonly substitutions: Map<() => Node>; + readonly substitutions: Map; } interface ReadsAndWrites { @@ -1274,7 +1274,7 @@ namespace ts.refactor.extractSymbol { const allTypeParameterUsages = createMap(); // Key is type ID const usagesPerScope: ScopeUsages[] = []; - const substitutionsPerScope: Map<() => Node>[] = []; + const substitutionsPerScope: Map[] = []; const functionErrorsPerScope: Diagnostic[][] = []; const constantErrorsPerScope: Diagnostic[][] = []; const visibleDeclarationsInExtractedRange: Symbol[] = []; @@ -1298,8 +1298,8 @@ namespace ts.refactor.extractSymbol { // initialize results for (const scope of scopes) { - usagesPerScope.push({ usages: createMap(), typeParameterUsages: createMap(), substitutions: createMap<() => Expression>() }); - substitutionsPerScope.push(createMap<() => Expression>()); + usagesPerScope.push({ usages: createMap(), typeParameterUsages: createMap(), substitutions: createMap() }); + substitutionsPerScope.push(createMap()); functionErrorsPerScope.push( isFunctionLikeDeclaration(scope) && scope.kind !== SyntaxKind.FunctionDeclaration @@ -1598,20 +1598,20 @@ namespace ts.refactor.extractSymbol { } } - function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol, scopeDecl: Node, isTypeNode: boolean): () => (PropertyAccessExpression | EntityName) { + function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName { if (!symbol) { return undefined; } if (symbol.getDeclarations().some(d => d.parent === scopeDecl)) { - return () => createIdentifier(symbol.name); + return createIdentifier(symbol.name); } const prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode); if (prefix === undefined) { return undefined; } return isTypeNode - ? () => createQualifiedName(prefix(), createIdentifier(symbol.name)) - : () => createPropertyAccess(prefix(), symbol.name); + ? createQualifiedName(prefix, createIdentifier(symbol.name)) + : createPropertyAccess(prefix, symbol.name); } } From 7a4c3314e816bc7a7589d1e6e52328c38f1fc693 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 5 Oct 2017 16:47:24 -0700 Subject: [PATCH 057/246] Visit default export expressions (#18977) --- src/compiler/transformers/module/module.ts | 4 ++-- ...amicImportInDefaultExportExpression.errors.txt | 11 +++++++++++ .../dynamicImportInDefaultExportExpression.js | 15 +++++++++++++++ ...dynamicImportInDefaultExportExpression.symbols | 8 ++++++++ .../dynamicImportInDefaultExportExpression.types | 13 +++++++++++++ .../dynamicImportInDefaultExportExpression.ts | 7 +++++++ 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/dynamicImportInDefaultExportExpression.errors.txt create mode 100644 tests/baselines/reference/dynamicImportInDefaultExportExpression.js create mode 100644 tests/baselines/reference/dynamicImportInDefaultExportExpression.symbols create mode 100644 tests/baselines/reference/dynamicImportInDefaultExportExpression.types create mode 100644 tests/cases/compiler/dynamicImportInDefaultExportExpression.ts diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 145ac07c2f2e2..ecbef6856497c 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -861,10 +861,10 @@ namespace ts { if (original && hasAssociatedEndOfDeclarationMarker(original)) { // Defer exports until we encounter an EndOfDeclarationMarker node const id = getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], createIdentifier("default"), node.expression, /*location*/ node, /*allowComments*/ true); + deferredExports[id] = appendExportStatement(deferredExports[id], createIdentifier("default"), visitNode(node.expression, importCallExpressionVisitor), /*location*/ node, /*allowComments*/ true); } else { - statements = appendExportStatement(statements, createIdentifier("default"), node.expression, /*location*/ node, /*allowComments*/ true); + statements = appendExportStatement(statements, createIdentifier("default"), visitNode(node.expression, importCallExpressionVisitor), /*location*/ node, /*allowComments*/ true); } return singleOrMany(statements); diff --git a/tests/baselines/reference/dynamicImportInDefaultExportExpression.errors.txt b/tests/baselines/reference/dynamicImportInDefaultExportExpression.errors.txt new file mode 100644 index 0000000000000..8bf6704b74358 --- /dev/null +++ b/tests/baselines/reference/dynamicImportInDefaultExportExpression.errors.txt @@ -0,0 +1,11 @@ +tests/cases/compiler/dynamicImportInDefaultExportExpression.ts(3,23): error TS2307: Cannot find module './foo2'. + + +==== tests/cases/compiler/dynamicImportInDefaultExportExpression.ts (1 errors) ==== + export default { + getInstance: function () { + return import('./foo2'); + ~~~~~~~~ +!!! error TS2307: Cannot find module './foo2'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/dynamicImportInDefaultExportExpression.js b/tests/baselines/reference/dynamicImportInDefaultExportExpression.js new file mode 100644 index 0000000000000..75e5e0d57a22e --- /dev/null +++ b/tests/baselines/reference/dynamicImportInDefaultExportExpression.js @@ -0,0 +1,15 @@ +//// [dynamicImportInDefaultExportExpression.ts] +export default { + getInstance: function () { + return import('./foo2'); + } +} + +//// [dynamicImportInDefaultExportExpression.js] +"use strict"; +exports.__esModule = true; +exports["default"] = { + getInstance: function () { + return Promise.resolve().then(function () { return require('./foo2'); }); + } +}; diff --git a/tests/baselines/reference/dynamicImportInDefaultExportExpression.symbols b/tests/baselines/reference/dynamicImportInDefaultExportExpression.symbols new file mode 100644 index 0000000000000..d16b5f0a374f3 --- /dev/null +++ b/tests/baselines/reference/dynamicImportInDefaultExportExpression.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/dynamicImportInDefaultExportExpression.ts === +export default { + getInstance: function () { +>getInstance : Symbol(getInstance, Decl(dynamicImportInDefaultExportExpression.ts, 0, 16)) + + return import('./foo2'); + } +} diff --git a/tests/baselines/reference/dynamicImportInDefaultExportExpression.types b/tests/baselines/reference/dynamicImportInDefaultExportExpression.types new file mode 100644 index 0000000000000..c75894a17ffbd --- /dev/null +++ b/tests/baselines/reference/dynamicImportInDefaultExportExpression.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/dynamicImportInDefaultExportExpression.ts === +export default { +>{ getInstance: function () { return import('./foo2'); }} : { getInstance: () => Promise; } + + getInstance: function () { +>getInstance : () => Promise +>function () { return import('./foo2'); } : () => Promise + + return import('./foo2'); +>import('./foo2') : Promise +>'./foo2' : "./foo2" + } +} diff --git a/tests/cases/compiler/dynamicImportInDefaultExportExpression.ts b/tests/cases/compiler/dynamicImportInDefaultExportExpression.ts new file mode 100644 index 0000000000000..0e6ad95886bd0 --- /dev/null +++ b/tests/cases/compiler/dynamicImportInDefaultExportExpression.ts @@ -0,0 +1,7 @@ +// @skipLibCheck: true +// @lib: es6 +export default { + getInstance: function () { + return import('./foo2'); + } +} \ No newline at end of file From 70e259aba368349f075ebe389e2f5c16dfec41db Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 6 Oct 2017 09:16:57 -0700 Subject: [PATCH 058/246] Always use callback parameter code path, but stricter if necessary --- src/compiler/checker.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5ea946aa89888..305e47374cb4e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -503,6 +503,12 @@ namespace ts { Inferential = 2, // Inferential typing } + const enum CallbackCheck { + None, + Bivariant, + Strict, + } + const builtinGlobals = createSymbolTable(); builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol); @@ -8510,7 +8516,7 @@ namespace ts { function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { - return compareSignaturesRelated(source, target, /*checkAsCallback*/ false, ignoreReturnTypes, /*reportErrors*/ false, + return compareSignaturesRelated(source, target, CallbackCheck.None, ignoreReturnTypes, /*reportErrors*/ false, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False; } @@ -8521,7 +8527,7 @@ namespace ts { */ function compareSignaturesRelated(source: Signature, target: Signature, - checkAsCallback: boolean, + callbackCheck: CallbackCheck, ignoreReturnTypes: boolean, reportErrors: boolean, errorReporter: ErrorReporter, @@ -8540,7 +8546,7 @@ namespace ts { } const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; - const strictVariance = !checkAsCallback && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && + const strictVariance = !callbackCheck && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; let result = Ternary.True; @@ -8579,11 +8585,11 @@ namespace ts { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const callbacks = !strictVariance && sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate && + const callbacks = sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate && (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); const related = callbacks ? - compareSignaturesRelated(targetSig, sourceSig, /*checkAsCallback*/ true, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : - !checkAsCallback && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); + compareSignaturesRelated(targetSig, sourceSig, strictVariance ? CallbackCheck.Strict : CallbackCheck.Bivariant, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : + !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); if (!related) { if (reportErrors) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, @@ -8618,7 +8624,7 @@ namespace ts { // When relating callback signatures, we still need to relate return types bi-variantly as otherwise // the containing type wouldn't be co-variant. For example, interface Foo { add(cb: () => T): void } // wouldn't be co-variant for T without this rule. - result &= checkAsCallback && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) || + result &= callbackCheck === CallbackCheck.Bivariant && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) || compareTypes(sourceReturnType, targetReturnType, reportErrors); } @@ -9715,7 +9721,7 @@ namespace ts { */ function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean): Ternary { return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, - /*checkAsCallback*/ false, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); + CallbackCheck.None, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); } function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary { From c8d52609142cd61c50b9593ee42ba8a4f649d885 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 6 Oct 2017 09:17:18 -0700 Subject: [PATCH 059/246] Accept new baselines --- .../strictFunctionTypesErrors.errors.txt | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 6a8204fb1478e..600a58638edde 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -40,22 +40,26 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(58,1): error TS2322: Type 'Fun Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(61,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, Object>'. Types of parameters 'x' and 'x' are incompatible. - Type 'Func' is not assignable to type 'Func'. - Types of parameters 'x' and 'x' are incompatible. - Type 'Object' is not assignable to type 'string'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(62,1): error TS2322: Type 'Func, string>' is not assignable to type 'Func, Object>'. Types of parameters 'x' and 'x' are incompatible. - Type 'Func' is not assignable to type 'Func'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(65,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. Types of parameters 'x' and 'x' are incompatible. - Type 'Func' is not assignable to type 'Func'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(66,1): error TS2322: Type 'Func, string>' is not assignable to type 'Func, string>'. Types of parameters 'x' and 'x' are incompatible. - Type 'Func' is not assignable to type 'Func'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(67,1): error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(74,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Type 'Func' is not assignable to type 'Func'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Object' is not assignable to type 'string'. tests/cases/compiler/strictFunctionTypesErrors.ts(75,1): error TS2322: Type 'Func>' is not assignable to type 'Func>'. Types of parameters 'x' and 'x' are incompatible. Type 'Object' is not assignable to type 'string'. @@ -85,13 +89,11 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(127,1): error TS2322: Type 'Cr Type 'Animal' is not assignable to type 'Dog'. tests/cases/compiler/strictFunctionTypesErrors.ts(133,1): error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'. Types of parameters 'f' and 'f' are incompatible. - Type '(x: Animal) => Animal' is not assignable to type '(x: Dog) => Dog'. - Type 'Animal' is not assignable to type 'Dog'. + Type 'Animal' is not assignable to type 'Dog'. tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'. Types of parameters 'f' and 'f' are incompatible. - Type '(x: Dog) => Dog' is not assignable to type '(x: Animal) => Animal'. - Types of parameters 'x' and 'x' are incompatible. - Type 'Animal' is not assignable to type 'Dog'. + Types of parameters 'x' and 'x' are incompatible. + Type 'Animal' is not assignable to type 'Dog'. ==== tests/cases/compiler/strictFunctionTypesErrors.ts (33 errors) ==== @@ -215,26 +217,28 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, Object>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Func' is not assignable to type 'Func'. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Object' is not assignable to type 'string'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. h3 = h2; // Error ~~ !!! error TS2322: Type 'Func, string>' is not assignable to type 'Func, Object>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Func' is not assignable to type 'Func'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. h3 = h4; // Ok h4 = h1; // Error ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Func' is not assignable to type 'Func'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. h4 = h2; // Error ~~ !!! error TS2322: Type 'Func, string>' is not assignable to type 'Func, string>'. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Func' is not assignable to type 'Func'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. h4 = h3; // Error ~~ !!! error TS2322: Type 'Func, Object>' is not assignable to type 'Func, string>'. @@ -249,6 +253,8 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. !!! error TS2322: Type 'Func' is not assignable to type 'Func'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Object' is not assignable to type 'string'. i1 = i3; // Error ~~ !!! error TS2322: Type 'Func>' is not assignable to type 'Func>'. @@ -347,13 +353,11 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f ~~~ !!! error TS2322: Type '(f: (x: Dog) => Dog) => void' is not assignable to type '(f: (x: Animal) => Animal) => void'. !!! error TS2322: Types of parameters 'f' and 'f' are incompatible. -!!! error TS2322: Type '(x: Animal) => Animal' is not assignable to type '(x: Dog) => Dog'. -!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. fc2 = fc1; // Error ~~~ !!! error TS2322: Type '(f: (x: Animal) => Animal) => void' is not assignable to type '(f: (x: Dog) => Dog) => void'. !!! error TS2322: Types of parameters 'f' and 'f' are incompatible. -!!! error TS2322: Type '(x: Dog) => Dog' is not assignable to type '(x: Animal) => Animal'. -!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. -!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. \ No newline at end of file From 7fcf51960ddc753754876c9905c84726ff0ff97e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 6 Oct 2017 09:22:10 -0700 Subject: [PATCH 060/246] Add tests --- .../strictFunctionTypesErrors.errors.txt | 43 +++++++++- .../reference/strictFunctionTypesErrors.js | 43 +++++++++- .../strictFunctionTypesErrors.symbols | 78 +++++++++++++++++ .../reference/strictFunctionTypesErrors.types | 84 +++++++++++++++++++ .../compiler/strictFunctionTypesErrors.ts | 22 +++++ 5 files changed, 267 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt index 600a58638edde..d8e36e43060d7 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.errors.txt +++ b/tests/baselines/reference/strictFunctionTypesErrors.errors.txt @@ -94,9 +94,17 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f Types of parameters 'f' and 'f' are incompatible. Types of parameters 'x' and 'x' are incompatible. Type 'Animal' is not assignable to type 'Dog'. +tests/cases/compiler/strictFunctionTypesErrors.ts(147,5): error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'. + Types of parameters 'cb' and 'cb' are incompatible. + Types of parameters 'x' and 'x' are incompatible. + Type 'Animal' is not assignable to type 'Dog'. +tests/cases/compiler/strictFunctionTypesErrors.ts(155,5): error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'. + Types of parameters 'cb' and 'cb' are incompatible. + Types of parameters 'x' and 'x' are incompatible. + Type 'Animal' is not assignable to type 'Dog'. -==== tests/cases/compiler/strictFunctionTypesErrors.ts (33 errors) ==== +==== tests/cases/compiler/strictFunctionTypesErrors.ts (35 errors) ==== export {} @@ -360,4 +368,35 @@ tests/cases/compiler/strictFunctionTypesErrors.ts(134,1): error TS2322: Type '(f !!! error TS2322: Types of parameters 'f' and 'f' are incompatible. !!! error TS2322: Types of parameters 'x' and 'x' are incompatible. !!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. - \ No newline at end of file + + // Verify that callback parameters aren't loosely checked when types + // originate in method declarations + + namespace n1 { + class Foo { + static f1(x: Animal): Animal { throw "wat"; } + static f2(x: Dog): Animal { throw "wat"; }; + } + declare let f1: (cb: typeof Foo.f1) => void; + declare let f2: (cb: typeof Foo.f2) => void; + f1 = f2; + f2 = f1; // Error + ~~ +!!! error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'. +!!! error TS2322: Types of parameters 'cb' and 'cb' are incompatible. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. + } + + namespace n2 { + type BivariantHack = { foo(x: Input): Output }["foo"]; + declare let f1: (cb: BivariantHack) => void; + declare let f2: (cb: BivariantHack) => void; + f1 = f2; + f2 = f1; // Error + ~~ +!!! error TS2322: Type '(cb: (x: Animal) => Animal) => void' is not assignable to type '(cb: (x: Dog) => Animal) => void'. +!!! error TS2322: Types of parameters 'cb' and 'cb' are incompatible. +!!! error TS2322: Types of parameters 'x' and 'x' are incompatible. +!!! error TS2322: Type 'Animal' is not assignable to type 'Dog'. + } \ No newline at end of file diff --git a/tests/baselines/reference/strictFunctionTypesErrors.js b/tests/baselines/reference/strictFunctionTypesErrors.js index 8e338fa030d0d..d0608f6c1acbc 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.js +++ b/tests/baselines/reference/strictFunctionTypesErrors.js @@ -133,7 +133,28 @@ declare let fc1: (f: (x: Animal) => Animal) => void; declare let fc2: (f: (x: Dog) => Dog) => void; fc1 = fc2; // Error fc2 = fc1; // Error - + +// Verify that callback parameters aren't loosely checked when types +// originate in method declarations + +namespace n1 { + class Foo { + static f1(x: Animal): Animal { throw "wat"; } + static f2(x: Dog): Animal { throw "wat"; }; + } + declare let f1: (cb: typeof Foo.f1) => void; + declare let f2: (cb: typeof Foo.f2) => void; + f1 = f2; + f2 = f1; // Error +} + +namespace n2 { + type BivariantHack = { foo(x: Input): Output }["foo"]; + declare let f1: (cb: BivariantHack) => void; + declare let f2: (cb: BivariantHack) => void; + f1 = f2; + f2 = f1; // Error +} //// [strictFunctionTypesErrors.js] "use strict"; @@ -195,3 +216,23 @@ animalCrate = dogCrate; // Error dogCrate = animalCrate; // Error fc1 = fc2; // Error fc2 = fc1; // Error +// Verify that callback parameters aren't loosely checked when types +// originate in method declarations +var n1; +(function (n1) { + var Foo = /** @class */ (function () { + function Foo() { + } + Foo.f1 = function (x) { throw "wat"; }; + Foo.f2 = function (x) { throw "wat"; }; + ; + return Foo; + }()); + f1 = f2; + f2 = f1; // Error +})(n1 || (n1 = {})); +var n2; +(function (n2) { + f1 = f2; + f2 = f1; // Error +})(n2 || (n2 = {})); diff --git a/tests/baselines/reference/strictFunctionTypesErrors.symbols b/tests/baselines/reference/strictFunctionTypesErrors.symbols index fd28775c5e13d..c85c337ca4448 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.symbols +++ b/tests/baselines/reference/strictFunctionTypesErrors.symbols @@ -424,3 +424,81 @@ fc2 = fc1; // Error >fc2 : Symbol(fc2, Decl(strictFunctionTypesErrors.ts, 131, 11)) >fc1 : Symbol(fc1, Decl(strictFunctionTypesErrors.ts, 130, 11)) +// Verify that callback parameters aren't loosely checked when types +// originate in method declarations + +namespace n1 { +>n1 : Symbol(n1, Decl(strictFunctionTypesErrors.ts, 133, 10)) + + class Foo { +>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14)) + + static f1(x: Animal): Animal { throw "wat"; } +>f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15)) +>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 140, 18)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) + + static f2(x: Dog): Animal { throw "wat"; }; +>f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53)) +>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 141, 18)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) + } + declare let f1: (cb: typeof Foo.f1) => void; +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15)) +>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 143, 21)) +>Foo.f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15)) +>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14)) +>f1 : Symbol(Foo.f1, Decl(strictFunctionTypesErrors.ts, 139, 15)) + + declare let f2: (cb: typeof Foo.f2) => void; +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15)) +>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 144, 21)) +>Foo.f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53)) +>Foo : Symbol(Foo, Decl(strictFunctionTypesErrors.ts, 138, 14)) +>f2 : Symbol(Foo.f2, Decl(strictFunctionTypesErrors.ts, 140, 53)) + + f1 = f2; +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15)) +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15)) + + f2 = f1; // Error +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 144, 15)) +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 143, 15)) +} + +namespace n2 { +>n2 : Symbol(n2, Decl(strictFunctionTypesErrors.ts, 147, 1)) + + type BivariantHack = { foo(x: Input): Output }["foo"]; +>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14)) +>Input : Symbol(Input, Decl(strictFunctionTypesErrors.ts, 150, 23)) +>Output : Symbol(Output, Decl(strictFunctionTypesErrors.ts, 150, 29)) +>foo : Symbol(foo, Decl(strictFunctionTypesErrors.ts, 150, 41)) +>x : Symbol(x, Decl(strictFunctionTypesErrors.ts, 150, 46)) +>Input : Symbol(Input, Decl(strictFunctionTypesErrors.ts, 150, 23)) +>Output : Symbol(Output, Decl(strictFunctionTypesErrors.ts, 150, 29)) + + declare let f1: (cb: BivariantHack) => void; +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15)) +>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 151, 21)) +>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) + + declare let f2: (cb: BivariantHack) => void; +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15)) +>cb : Symbol(cb, Decl(strictFunctionTypesErrors.ts, 152, 21)) +>BivariantHack : Symbol(BivariantHack, Decl(strictFunctionTypesErrors.ts, 149, 14)) +>Dog : Symbol(Dog, Decl(strictFunctionTypesErrors.ts, 89, 33)) +>Animal : Symbol(Animal, Decl(strictFunctionTypesErrors.ts, 87, 8)) + + f1 = f2; +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15)) +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15)) + + f2 = f1; // Error +>f2 : Symbol(f2, Decl(strictFunctionTypesErrors.ts, 152, 15)) +>f1 : Symbol(f1, Decl(strictFunctionTypesErrors.ts, 151, 15)) +} diff --git a/tests/baselines/reference/strictFunctionTypesErrors.types b/tests/baselines/reference/strictFunctionTypesErrors.types index 45deeebababee..1890279258ca9 100644 --- a/tests/baselines/reference/strictFunctionTypesErrors.types +++ b/tests/baselines/reference/strictFunctionTypesErrors.types @@ -480,3 +480,87 @@ fc2 = fc1; // Error >fc2 : (f: (x: Dog) => Dog) => void >fc1 : (f: (x: Animal) => Animal) => void +// Verify that callback parameters aren't loosely checked when types +// originate in method declarations + +namespace n1 { +>n1 : typeof n1 + + class Foo { +>Foo : Foo + + static f1(x: Animal): Animal { throw "wat"; } +>f1 : (x: Animal) => Animal +>x : Animal +>Animal : Animal +>Animal : Animal +>"wat" : "wat" + + static f2(x: Dog): Animal { throw "wat"; }; +>f2 : (x: Dog) => Animal +>x : Dog +>Dog : Dog +>Animal : Animal +>"wat" : "wat" + } + declare let f1: (cb: typeof Foo.f1) => void; +>f1 : (cb: (x: Animal) => Animal) => void +>cb : (x: Animal) => Animal +>Foo.f1 : (x: Animal) => Animal +>Foo : typeof Foo +>f1 : (x: Animal) => Animal + + declare let f2: (cb: typeof Foo.f2) => void; +>f2 : (cb: (x: Dog) => Animal) => void +>cb : (x: Dog) => Animal +>Foo.f2 : (x: Dog) => Animal +>Foo : typeof Foo +>f2 : (x: Dog) => Animal + + f1 = f2; +>f1 = f2 : (cb: (x: Dog) => Animal) => void +>f1 : (cb: (x: Animal) => Animal) => void +>f2 : (cb: (x: Dog) => Animal) => void + + f2 = f1; // Error +>f2 = f1 : (cb: (x: Animal) => Animal) => void +>f2 : (cb: (x: Dog) => Animal) => void +>f1 : (cb: (x: Animal) => Animal) => void +} + +namespace n2 { +>n2 : typeof n2 + + type BivariantHack = { foo(x: Input): Output }["foo"]; +>BivariantHack : (x: Input) => Output +>Input : Input +>Output : Output +>foo : (x: Input) => Output +>x : Input +>Input : Input +>Output : Output + + declare let f1: (cb: BivariantHack) => void; +>f1 : (cb: (x: Animal) => Animal) => void +>cb : (x: Animal) => Animal +>BivariantHack : (x: Input) => Output +>Animal : Animal +>Animal : Animal + + declare let f2: (cb: BivariantHack) => void; +>f2 : (cb: (x: Dog) => Animal) => void +>cb : (x: Dog) => Animal +>BivariantHack : (x: Input) => Output +>Dog : Dog +>Animal : Animal + + f1 = f2; +>f1 = f2 : (cb: (x: Dog) => Animal) => void +>f1 : (cb: (x: Animal) => Animal) => void +>f2 : (cb: (x: Dog) => Animal) => void + + f2 = f1; // Error +>f2 = f1 : (cb: (x: Animal) => Animal) => void +>f2 : (cb: (x: Dog) => Animal) => void +>f1 : (cb: (x: Animal) => Animal) => void +} diff --git a/tests/cases/compiler/strictFunctionTypesErrors.ts b/tests/cases/compiler/strictFunctionTypesErrors.ts index 95598d9d44425..3f86f2529c08e 100644 --- a/tests/cases/compiler/strictFunctionTypesErrors.ts +++ b/tests/cases/compiler/strictFunctionTypesErrors.ts @@ -133,3 +133,25 @@ declare let fc1: (f: (x: Animal) => Animal) => void; declare let fc2: (f: (x: Dog) => Dog) => void; fc1 = fc2; // Error fc2 = fc1; // Error + +// Verify that callback parameters aren't loosely checked when types +// originate in method declarations + +namespace n1 { + class Foo { + static f1(x: Animal): Animal { throw "wat"; } + static f2(x: Dog): Animal { throw "wat"; }; + } + declare let f1: (cb: typeof Foo.f1) => void; + declare let f2: (cb: typeof Foo.f2) => void; + f1 = f2; + f2 = f1; // Error +} + +namespace n2 { + type BivariantHack = { foo(x: Input): Output }["foo"]; + declare let f1: (cb: BivariantHack) => void; + declare let f2: (cb: BivariantHack) => void; + f1 = f2; + f2 = f1; // Error +} \ No newline at end of file From 5c9f8c56d95eee6bc897c8dfb64c398bf0e273fd Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Fri, 6 Oct 2017 10:20:12 -0700 Subject: [PATCH 061/246] Mark getSynthesizedDeepClone @internal --- src/compiler/factory.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 84c28abe1a51e..7d703ffe06222 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -74,6 +74,7 @@ namespace ts { /** * Creates a deep, memberwise clone of a node with no source map location. */ + /* @internal */ export function getSynthesizedDeepClone(node: T | undefined): T | undefined { return node ? getSynthesizedClone(visitEachChild(node, child => getSynthesizedDeepClone(child), nullTransformationContext)) From 3b9bbb3e55c91775b9b1633bcd4cf6417d280b6b Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 6 Oct 2017 10:31:45 -0700 Subject: [PATCH 062/246] Remove duplicate assignment (#18994) --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58248a8a9ee75..bb37d09888b40 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18451,9 +18451,8 @@ namespace ts { checkGrammarDecorators(node) || checkGrammarModifiers(node); checkVariableLikeDeclaration(node); - let func = getContainingFunction(node); + const func = getContainingFunction(node); if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) { - func = getContainingFunction(node); if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } From fbf8df66f006553bc720751389e18d98a3f9b3cf Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 6 Oct 2017 14:27:32 -0700 Subject: [PATCH 063/246] accept baselines --- tests/baselines/reference/APISample_jsdoc.js | 4 ++-- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++++ tests/baselines/reference/api/typescript.d.ts | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/APISample_jsdoc.js b/tests/baselines/reference/APISample_jsdoc.js index 33857d06a6a66..c74e188f38b22 100644 --- a/tests/baselines/reference/APISample_jsdoc.js +++ b/tests/baselines/reference/APISample_jsdoc.js @@ -101,7 +101,7 @@ function getAllTags(node: ts.Node) { function getSomeOtherTags(node: ts.Node) { const tags: (ts.JSDocTag | undefined)[] = []; - tags.push(ts.getJSDocAugmentsOrExtendsTag(node)); + tags.push(ts.getJSDocAugmentsTag(node)); tags.push(ts.getJSDocClassTag(node)); tags.push(ts.getJSDocReturnTag(node)); const type = ts.getJSDocTypeTag(node); @@ -200,7 +200,7 @@ function getAllTags(node) { } function getSomeOtherTags(node) { var tags = []; - tags.push(ts.getJSDocAugmentsOrExtendsTag(node)); + tags.push(ts.getJSDocAugmentsTag(node)); tags.push(ts.getJSDocClassTag(node)); tags.push(ts.getJSDocReturnTag(node)); var type = ts.getJSDocTypeTag(node); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3bb2ed1167488..ca8696b11fb8d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1442,6 +1442,10 @@ declare namespace ts { interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; } + /** + * Note that `@extends` is a synonym of `@augments`. + * Both tags are represented by this interface. + */ interface JSDocAugmentsTag extends JSDocTag { kind: SyntaxKind.JSDocAugmentsTag; class: ExpressionWithTypeArguments & { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index d41db2eb413ee..820be44f1f1c4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1442,6 +1442,10 @@ declare namespace ts { interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; } + /** + * Note that `@extends` is a synonym of `@augments`. + * Both tags are represented by this interface. + */ interface JSDocAugmentsTag extends JSDocTag { kind: SyntaxKind.JSDocAugmentsTag; class: ExpressionWithTypeArguments & { From 71f885212451e09da16c8808361c46f3fc38227f Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 6 Oct 2017 14:29:45 -0700 Subject: [PATCH 064/246] Have getNameOfDeclaration return `x` for `export default x`. (#18616) --- src/compiler/binder.ts | 6 ++- src/compiler/utilities.ts | 46 +++++++++++-------- src/services/findAllReferences.ts | 5 +- src/services/importTracker.ts | 3 -- src/services/symbolDisplay.ts | 20 +++++--- .../duplicateExportAssignments.errors.txt | 44 +++++++++--------- .../baselines/reference/es5-commonjs7.symbols | 2 +- .../reference/exportDefaultVariable.symbols | 2 +- ...ationBindMultipleDefaultExports.errors.txt | 4 +- .../multipleDefaultExports01.errors.txt | 4 +- .../multipleExportAssignments.errors.txt | 8 ++-- ...AssignmentsInAmbientDeclaration.errors.txt | 8 ++-- .../reference/typeAliasExport.symbols | 2 +- ...indAllRefsDefaultImportThroughNamespace.ts | 15 +++--- .../findAllRefsForDefaultExport04.ts | 6 +-- ...currencesIsDefinitionOfComputedProperty.ts | 6 ++- 16 files changed, 100 insertions(+), 81 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 796c960342384..28193535ce9a2 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -230,6 +230,10 @@ namespace ts { // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. function getDeclarationName(node: Declaration): __String { + if (node.kind === SyntaxKind.ExportAssignment) { + return (node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; + } + const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { @@ -261,8 +265,6 @@ namespace ts { return InternalSymbolName.Index; case SyntaxKind.ExportDeclaration: return InternalSymbolName.ExportStar; - case SyntaxKind.ExportAssignment: - return (node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ... diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f0eb394adb7dd..ce209cbd8116d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4112,27 +4112,35 @@ namespace ts { if (!declaration) { return undefined; } - if (isJSDocPropertyLikeTag(declaration) && declaration.name.kind === SyntaxKind.QualifiedName) { - return declaration.name.right; - } - if (declaration.kind === SyntaxKind.BinaryExpression) { - const expr = declaration as BinaryExpression; - switch (getSpecialPropertyAssignmentKind(expr)) { - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.ThisProperty: - case SpecialPropertyAssignmentKind.Property: - case SpecialPropertyAssignmentKind.PrototypeProperty: - return (expr.left as PropertyAccessExpression).name; - default: - return undefined; + switch (declaration.kind) { + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocParameterTag: { + const { name } = declaration as JSDocPropertyLikeTag; + if (name.kind === SyntaxKind.QualifiedName) { + return name.right; + } + break; + } + case SyntaxKind.BinaryExpression: { + const expr = declaration as BinaryExpression; + switch (getSpecialPropertyAssignmentKind(expr)) { + case SpecialPropertyAssignmentKind.ExportsProperty: + case SpecialPropertyAssignmentKind.ThisProperty: + case SpecialPropertyAssignmentKind.Property: + case SpecialPropertyAssignmentKind.PrototypeProperty: + return (expr.left as PropertyAccessExpression).name; + default: + return undefined; + } + } + case SyntaxKind.JSDocTypedefTag: + return getNameOfJSDocTypedef(declaration as JSDocTypedefTag); + case SyntaxKind.ExportAssignment: { + const { expression } = declaration as ExportAssignment; + return isIdentifier(expression) ? expression : undefined; } } - else if (declaration.kind === SyntaxKind.JSDocTypedefTag) { - return getNameOfJSDocTypedef(declaration as JSDocTypedefTag); - } - else { - return (declaration as NamedDeclaration).name; - } + return (declaration as NamedDeclaration).name; } /** diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index d4e660295a078..e43a2cbfd8e64 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -482,7 +482,10 @@ namespace ts.FindAllReferences.Core { /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search { // Note: if this is an external module symbol, the name doesn't include quotes. - const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; + const { + text = stripQuotes(unescapeLeadingUnderscores((getLocalSymbolForExportDefault(symbol) || symbol).escapedName)), + allSearchSymbols = undefined, + } = searchOptions; const escapedText = escapeLeadingUnderscores(text); const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); return { diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index a615223021875..f12df4613c041 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -609,9 +609,6 @@ namespace ts.FindAllReferences { } return forEach(symbol.declarations, decl => { - if (isExportAssignment(decl)) { - return isIdentifier(decl.expression) ? decl.expression.escapedText : undefined; - } const name = getNameOfDeclaration(decl); return name && name.kind === SyntaxKind.Identifier && name.escapedText; }); diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index a399610d823e4..d38d21f109293 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -341,13 +341,19 @@ namespace ts.SymbolDisplay { } if (symbolFlags & SymbolFlags.Alias) { addNewLineIfDisplayPartsExist(); - if (symbol.declarations[0].kind === SyntaxKind.NamespaceExportDeclaration) { - displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); - displayParts.push(spacePart()); - displayParts.push(keywordPart(SyntaxKind.NamespaceKeyword)); - } - else { - displayParts.push(keywordPart(SyntaxKind.ImportKeyword)); + switch (symbol.declarations[0].kind) { + case SyntaxKind.NamespaceExportDeclaration: + displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); + displayParts.push(spacePart()); + displayParts.push(keywordPart(SyntaxKind.NamespaceKeyword)); + break; + case SyntaxKind.ExportAssignment: + displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); + displayParts.push(spacePart()); + displayParts.push(keywordPart((symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); + break; + default: + displayParts.push(keywordPart(SyntaxKind.ImportKeyword)); } displayParts.push(spacePart()); addFullSymbolName(symbol); diff --git a/tests/baselines/reference/duplicateExportAssignments.errors.txt b/tests/baselines/reference/duplicateExportAssignments.errors.txt index 17ad0a398479f..0ad9507c9a67d 100644 --- a/tests/baselines/reference/duplicateExportAssignments.errors.txt +++ b/tests/baselines/reference/duplicateExportAssignments.errors.txt @@ -1,34 +1,34 @@ -tests/cases/conformance/externalModules/foo1.ts(3,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo1.ts(4,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo2.ts(3,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo2.ts(4,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo3.ts(7,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo3.ts(8,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo4.ts(1,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo4.ts(8,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo5.ts(4,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo5.ts(5,1): error TS2300: Duplicate identifier 'export='. -tests/cases/conformance/externalModules/foo5.ts(6,1): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo1.ts(3,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo1.ts(4,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo2.ts(3,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo2.ts(4,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo3.ts(7,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo3.ts(8,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo4.ts(1,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo4.ts(8,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo5.ts(4,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo5.ts(5,10): error TS2300: Duplicate identifier 'export='. +tests/cases/conformance/externalModules/foo5.ts(6,10): error TS2300: Duplicate identifier 'export='. ==== tests/cases/conformance/externalModules/foo1.ts (2 errors) ==== var x = 10; var y = 20; export = x; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = y; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. ==== tests/cases/conformance/externalModules/foo2.ts (2 errors) ==== var x = 10; class y {}; export = x; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = y; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. ==== tests/cases/conformance/externalModules/foo3.ts (2 errors) ==== @@ -39,15 +39,15 @@ tests/cases/conformance/externalModules/foo5.ts(6,1): error TS2300: Duplicate id y: number; } export = x; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = y; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. ==== tests/cases/conformance/externalModules/foo4.ts (2 errors) ==== export = x; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. function x(){ return 42; @@ -56,7 +56,7 @@ tests/cases/conformance/externalModules/foo5.ts(6,1): error TS2300: Duplicate id return 42; } export = y; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. ==== tests/cases/conformance/externalModules/foo5.ts (3 errors) ==== @@ -64,12 +64,12 @@ tests/cases/conformance/externalModules/foo5.ts(6,1): error TS2300: Duplicate id var y = "test"; var z = {}; export = x; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = y; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = z; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. \ No newline at end of file diff --git a/tests/baselines/reference/es5-commonjs7.symbols b/tests/baselines/reference/es5-commonjs7.symbols index ed8247a68783a..eb6dc06257351 100644 --- a/tests/baselines/reference/es5-commonjs7.symbols +++ b/tests/baselines/reference/es5-commonjs7.symbols @@ -1,6 +1,6 @@ === tests/cases/compiler/test.d.ts === export default undefined; ->undefined : Symbol(default) +>undefined : Symbol(undefined) export var __esModule; >__esModule : Symbol(__esModule, Decl(test.d.ts, 1, 10)) diff --git a/tests/baselines/reference/exportDefaultVariable.symbols b/tests/baselines/reference/exportDefaultVariable.symbols index cd7ebed926c78..9c924c32f4e6a 100644 --- a/tests/baselines/reference/exportDefaultVariable.symbols +++ b/tests/baselines/reference/exportDefaultVariable.symbols @@ -6,6 +6,6 @@ declare var io: any; declare module 'module' { export default io; ->io : Symbol(default, Decl(exportDefaultVariable.ts, 2, 11)) +>io : Symbol(io, Decl(exportDefaultVariable.ts, 2, 11)) } diff --git a/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt b/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt index 9a9a7a12db9ca..246b8f20cac73 100644 --- a/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt +++ b/tests/baselines/reference/jsFileCompilationBindMultipleDefaultExports.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/a.js(1,22): error TS2528: A module cannot have multiple default exports. tests/cases/compiler/a.js(1,22): error TS2652: Merged declaration 'a' cannot include a default export declaration. Consider adding a separate 'export default a' declaration instead. -tests/cases/compiler/a.js(3,1): error TS2528: A module cannot have multiple default exports. +tests/cases/compiler/a.js(3,15): error TS2528: A module cannot have multiple default exports. tests/cases/compiler/a.js(3,16): error TS1109: Expression expected. tests/cases/compiler/a.js(3,20): error TS2652: Merged declaration 'a' cannot include a default export declaration. Consider adding a separate 'export default a' declaration instead. @@ -13,7 +13,7 @@ tests/cases/compiler/a.js(3,20): error TS2652: Merged declaration 'a' cannot inc !!! error TS2652: Merged declaration 'a' cannot include a default export declaration. Consider adding a separate 'export default a' declaration instead. } export default var a = 10; - ~~~~~~~~~~~~~~ + !!! error TS2528: A module cannot have multiple default exports. ~~~ !!! error TS1109: Expression expected. diff --git a/tests/baselines/reference/multipleDefaultExports01.errors.txt b/tests/baselines/reference/multipleDefaultExports01.errors.txt index b53d4113dedcd..eff0203387c4e 100644 --- a/tests/baselines/reference/multipleDefaultExports01.errors.txt +++ b/tests/baselines/reference/multipleDefaultExports01.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/es6/modules/m1.ts(1,22): error TS2528: A module cannot have multiple default exports. tests/cases/conformance/es6/modules/m1.ts(5,25): error TS2528: A module cannot have multiple default exports. -tests/cases/conformance/es6/modules/m1.ts(10,1): error TS2528: A module cannot have multiple default exports. +tests/cases/conformance/es6/modules/m1.ts(10,16): error TS2528: A module cannot have multiple default exports. tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typeof foo' is not callable. Did you mean to include 'new'? @@ -19,7 +19,7 @@ tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typ var x = 10; export default x; - ~~~~~~~~~~~~~~~~~ + ~ !!! error TS2528: A module cannot have multiple default exports. ==== tests/cases/conformance/es6/modules/m2.ts (1 errors) ==== diff --git a/tests/baselines/reference/multipleExportAssignments.errors.txt b/tests/baselines/reference/multipleExportAssignments.errors.txt index 5fbabc2b4db16..c9f5eb7cf79f6 100644 --- a/tests/baselines/reference/multipleExportAssignments.errors.txt +++ b/tests/baselines/reference/multipleExportAssignments.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/multipleExportAssignments.ts(13,1): error TS2300: Duplicate identifier 'export='. -tests/cases/compiler/multipleExportAssignments.ts(14,1): error TS2300: Duplicate identifier 'export='. +tests/cases/compiler/multipleExportAssignments.ts(13,10): error TS2300: Duplicate identifier 'export='. +tests/cases/compiler/multipleExportAssignments.ts(14,10): error TS2300: Duplicate identifier 'export='. ==== tests/cases/compiler/multipleExportAssignments.ts (2 errors) ==== @@ -16,10 +16,10 @@ tests/cases/compiler/multipleExportAssignments.ts(14,1): error TS2300: Duplicate test2(): connectModule; }; export = server; - ~~~~~~~~~~~~~~~~ + ~~~~~~ !!! error TS2300: Duplicate identifier 'export='. export = connectExport; - ~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~ !!! error TS2300: Duplicate identifier 'export='. \ No newline at end of file diff --git a/tests/baselines/reference/multipleExportAssignmentsInAmbientDeclaration.errors.txt b/tests/baselines/reference/multipleExportAssignmentsInAmbientDeclaration.errors.txt index c6427a5cc28e5..792e2dd5968f4 100644 --- a/tests/baselines/reference/multipleExportAssignmentsInAmbientDeclaration.errors.txt +++ b/tests/baselines/reference/multipleExportAssignmentsInAmbientDeclaration.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts(4,5): error TS2300: Duplicate identifier 'export='. -tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts(5,5): error TS2300: Duplicate identifier 'export='. +tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts(4,14): error TS2300: Duplicate identifier 'export='. +tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts(5,14): error TS2300: Duplicate identifier 'export='. ==== tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts (2 errors) ==== @@ -7,9 +7,9 @@ tests/cases/compiler/multipleExportAssignmentsInAmbientDeclaration.ts(5,5): erro var a: number var b: number; export = a; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. export = b; - ~~~~~~~~~~~ + ~ !!! error TS2300: Duplicate identifier 'export='. } \ No newline at end of file diff --git a/tests/baselines/reference/typeAliasExport.symbols b/tests/baselines/reference/typeAliasExport.symbols index e019ca7a10b06..5ffe181ca70d3 100644 --- a/tests/baselines/reference/typeAliasExport.symbols +++ b/tests/baselines/reference/typeAliasExport.symbols @@ -1,7 +1,7 @@ === tests/cases/compiler/typeAliasExport.ts === declare module "a" { export default undefined ->undefined : Symbol(default) +>undefined : Symbol(undefined) export var a; >a : Symbol(a, Decl(typeAliasExport.ts, 2, 12), Decl(typeAliasExport.ts, 2, 15)) diff --git a/tests/cases/fourslash/findAllRefsDefaultImportThroughNamespace.ts b/tests/cases/fourslash/findAllRefsDefaultImportThroughNamespace.ts index e5f7763132413..1411a106c89b6 100644 --- a/tests/cases/fourslash/findAllRefsDefaultImportThroughNamespace.ts +++ b/tests/cases/fourslash/findAllRefsDefaultImportThroughNamespace.ts @@ -1,7 +1,7 @@ /// // @Filename: /a.ts -////export default function [|{| "isWriteAccess": true, "isDefinition": true |}f|]() {} +////export [|{| "isWriteAccess": true, "isDefinition": true |}default|] function [|{| "isWriteAccess": true, "isDefinition": true |}f|]() {} // @Filename: /b.ts ////export import a = require("./a"); @@ -13,16 +13,17 @@ ////declare const x: { [|{| "isWriteAccess": true, "isDefinition": true |}default|]: number }; ////x.[|default|]; -const [r0, r1, r2, r3] = test.ranges(); +const [r0, r1, r2, r3, r4] = test.ranges(); -verify.singleReferenceGroup("function f(): void", [r0, r1]); -verify.singleReferenceGroup("(property) default: number", [r2, r3]); +verify.referenceGroups([r0], [{ definition: "function f(): void", ranges: [r1, r2] }]); +verify.singleReferenceGroup("function f(): void", [r1, r2]); +verify.singleReferenceGroup("(property) default: number", [r3, r4]); -verify.rangesAreRenameLocations([r0]); +verify.rangesAreRenameLocations([r1]); // Can't rename a default import. -goTo.rangeStart(r1); +goTo.rangeStart(r2); verify.renameInfoFailed(); // Can rename a default property. -verify.rangesAreRenameLocations([r2, r3]); +verify.rangesAreRenameLocations([r3, r4]); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts index 1b5eb7a282db8..093910d1cb5e4 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts @@ -14,12 +14,10 @@ verify.referenceGroups([r0, r2], [ { definition: "import a", ranges: [r3, r4] } ]); verify.referenceGroups(r1, [ - // TODO:GH#17990 - { definition: "import default", ranges: [r1] }, + { definition: "export default a", ranges: [r1] }, { definition: "import a", ranges: [r3, r4] }, ]); verify.referenceGroups([r3, r4], [ { definition: "import a", ranges: [r3, r4] }, - // TODO:GH#17990 - { definition: "import default", ranges: [r1] }, + { definition: "export default a", ranges: [r1] }, ]); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts index 7d6cb0a48afb9..329a72c30fdaa 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts @@ -6,4 +6,8 @@ const ranges = test.ranges(); const [r0, r1, r2] = ranges; verify.referenceGroups(r0, [{ definition: '(property) ["foo"]: number', ranges }]); -verify.referenceGroups([r1, r2], undefined); // TODO: fix +verify.referenceGroups([r1, r2], [ + // TODO: these are the same thing, should be in the same group. + { definition: "(property) [\"foo\"]: number", ranges: [r0] }, + { definition: "(property) [\"foo\"]: number", ranges: [r1, r2] }, +]); From e821c2b6e9f244264779045fd1720fb9d16c0bb2 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 6 Oct 2017 15:05:00 -0700 Subject: [PATCH 065/246] A parameter not declared as a rest parameter is not one (#18825) --- src/compiler/checker.ts | 2 +- src/compiler/utilities.ts | 22 ++++--------------- ...ileCompilationRestParamJsDocFunction.types | 4 ++-- .../reference/jsdocPrefixPostfixParsing.types | 2 +- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1a60c3c5e23f..a8e18c432a6bb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20298,7 +20298,7 @@ namespace ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (!hasDeclaredRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { + if (!hasRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { return; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ce209cbd8116d..bdf8d81aa966c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1604,26 +1604,12 @@ namespace ts { } export function hasRestParameter(s: SignatureDeclaration): boolean { - return isRestParameter(lastOrUndefined(s.parameters)); + const last = lastOrUndefined(s.parameters); + return last && isRestParameter(last); } - export function hasDeclaredRestParameter(s: SignatureDeclaration): boolean { - return isDeclaredRestParam(lastOrUndefined(s.parameters)); - } - - export function isRestParameter(node: ParameterDeclaration) { - if (isInJavaScriptFile(node)) { - if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType || - forEach(getJSDocParameterTags(node), - t => t.typeExpression && t.typeExpression.type.kind === SyntaxKind.JSDocVariadicType)) { - return true; - } - } - return isDeclaredRestParam(node); - } - - export function isDeclaredRestParam(node: ParameterDeclaration) { - return node && node.dotDotDotToken !== undefined; + export function isRestParameter(node: ParameterDeclaration): boolean { + return node.dotDotDotToken !== undefined; } export const enum AssignmentKind { diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types index 54bc7938689b2..72c3388f2262b 100644 --- a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types @@ -10,7 +10,7 @@ * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { ->apply : (func: Function, thisArg: any, ...args: any[]) => any +>apply : (func: Function, thisArg: any, args: any[]) => any >func : Function >thisArg : any >args : any[] @@ -84,5 +84,5 @@ function apply(func, thisArg, args) { } export default apply; ->apply : (func: Function, thisArg: any, ...args: any[]) => any +>apply : (func: Function, thisArg: any, args: any[]) => any diff --git a/tests/baselines/reference/jsdocPrefixPostfixParsing.types b/tests/baselines/reference/jsdocPrefixPostfixParsing.types index b5ddec68cba85..9961af48e27cb 100644 --- a/tests/baselines/reference/jsdocPrefixPostfixParsing.types +++ b/tests/baselines/reference/jsdocPrefixPostfixParsing.types @@ -16,7 +16,7 @@ * @param {...number?[]!} k - (number[] | null)[] */ function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) { ->f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, ...e: (number | null)[], f: number[] | null, g: number[] | null, h: number[] | null, i: number[][], j: number[][] | null, k: (number[] | null)[]) => void +>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, e: (number | null)[], f: number[] | null, g: number[] | null, h: number[] | null, i: number[][], j: number[][] | null, k: (number[] | null)[]) => void >x : number[] >y : number[] >z : number[] From 0afaadba3b83dfbad89a8c2c5d812ef8ab783361 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 6 Oct 2017 15:56:39 -0700 Subject: [PATCH 066/246] add error for multiple tags --- src/compiler/checker.ts | 14 ++++-- src/compiler/diagnosticMessages.json | 4 ++ src/compiler/utilities.ts | 6 +++ .../fourslash/jsDocAugmentsAndExtends.ts | 50 +++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/jsDocAugmentsAndExtends.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 718fd76625f01..31c9acd8fb136 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20009,14 +20009,20 @@ namespace ts { } function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void { - const cls = getJSDocHost(node); - if (!isClassDeclaration(cls) && !isClassExpression(cls)) { - error(cls, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration); + const classLike = getJSDocHost(node); + if (!isClassDeclaration(classLike) && !isClassExpression(classLike)) { + error(classLike, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration); return; } + const augmentsTags = getAllJSDocTagsOfKind(classLike, SyntaxKind.JSDocAugmentsTag); + Debug.assert(augmentsTags.length > 0); + if (augmentsTags.length > 1) { + error(augmentsTags[1], Diagnostics.The_total_number_of_augments_and_extends_tags_allowed_for_a_single_class_declaration_is_at_most_1); + } + const name = getIdentifierFromEntityNameExpression(node.class.expression); - const extend = getClassExtendsHeritageClauseElement(cls); + const extend = getClassExtendsHeritageClauseElement(classLike); if (extend) { const className = getIdentifierFromEntityNameExpression(extend.expression); if (className && name.escapedText !== className.escapedText) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f3d6d4fcc4706..64c4d99d3496a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3527,6 +3527,10 @@ "category": "Error", "code": 8024 }, + "The total number of `@augments` and `@extends` tags allowed for a single class declaration is at most 1.": { + "category": "Error", + "code": 8025 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f0eb394adb7dd..825b310ddeb8b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4247,6 +4247,12 @@ namespace ts { return find(tags, doc => doc.kind === kind); } + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ + export function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray | undefined { + const tags = getJSDocTags(node); + return filter(tags, doc => doc.kind === kind); + } + } // Simple node tests of the form `node.kind === SyntaxKind.Foo`. diff --git a/tests/cases/fourslash/jsDocAugmentsAndExtends.ts b/tests/cases/fourslash/jsDocAugmentsAndExtends.ts new file mode 100644 index 0000000000000..e76a617a3cff9 --- /dev/null +++ b/tests/cases/fourslash/jsDocAugmentsAndExtends.ts @@ -0,0 +1,50 @@ +/// + +// @allowJs: true +// @checkJs: true +// @Filename: dummy.js + +//// /** +//// * @augments {Thing} +//// * @extends {Thing} +//// */ +//// class MyStringThing extends Thing { +//// constructor() { +//// var x = this.mine; +//// x/**/; +//// } +//// } + +// @Filename: declarations.d.ts +//// declare class Thing { +//// mine: T; +//// } + +// if more than one tag is present, report an error and take the type of the first entry. + +goTo.marker(); +verify.quickInfoIs("(local var) x: number"); +verify.getSemanticDiagnostics( +`[ + { + "message": "The total number of \`@augments\` and \`@extends\` tags allowed for a single class declaration is at most 1.", + "start": 36, + "length": 24, + "category": "error", + "code": 8025 + }, + { + "message": "Constructors for derived classes must contain a \'super\' call.", + "start": 105, + "length": 59, + "category": "error", + "code": 2377 + }, + { + "message": "\'super\' must be called before accessing \'this\' in the constructor of a derived class.", + "start": 137, + "length": 4, + "category": "error", + "code": 17009 + } +]`); \ No newline at end of file From 932b1b038c712b73eda432b5296263fe32af6a6d Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 6 Oct 2017 16:16:37 -0700 Subject: [PATCH 067/246] better error message --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- .../cases/fourslash/jsDocAugmentsAndExtends.ts | 17 ++--------------- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 31c9acd8fb136..aa5d10c475c8f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20018,7 +20018,7 @@ namespace ts { const augmentsTags = getAllJSDocTagsOfKind(classLike, SyntaxKind.JSDocAugmentsTag); Debug.assert(augmentsTags.length > 0); if (augmentsTags.length > 1) { - error(augmentsTags[1], Diagnostics.The_total_number_of_augments_and_extends_tags_allowed_for_a_single_class_declaration_is_at_most_1); + error(augmentsTags[1], Diagnostics.Class_declarations_cannot_have_more_than_one_augments_or_extends_tag); } const name = getIdentifierFromEntityNameExpression(node.class.expression); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 64c4d99d3496a..e0de43a97db6c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3527,7 +3527,7 @@ "category": "Error", "code": 8024 }, - "The total number of `@augments` and `@extends` tags allowed for a single class declaration is at most 1.": { + "Class declarations cannot have more than one `@augments` or `@extends` tag.": { "category": "Error", "code": 8025 }, diff --git a/tests/cases/fourslash/jsDocAugmentsAndExtends.ts b/tests/cases/fourslash/jsDocAugmentsAndExtends.ts index e76a617a3cff9..10f33260268ac 100644 --- a/tests/cases/fourslash/jsDocAugmentsAndExtends.ts +++ b/tests/cases/fourslash/jsDocAugmentsAndExtends.ts @@ -10,6 +10,7 @@ //// */ //// class MyStringThing extends Thing { //// constructor() { +//// super(); //// var x = this.mine; //// x/**/; //// } @@ -27,24 +28,10 @@ verify.quickInfoIs("(local var) x: number"); verify.getSemanticDiagnostics( `[ { - "message": "The total number of \`@augments\` and \`@extends\` tags allowed for a single class declaration is at most 1.", + "message": "Class declarations cannot have more than one \`@augments\` or \`@extends\` tag.", "start": 36, "length": 24, "category": "error", "code": 8025 - }, - { - "message": "Constructors for derived classes must contain a \'super\' call.", - "start": 105, - "length": 59, - "category": "error", - "code": 2377 - }, - { - "message": "\'super\' must be called before accessing \'this\' in the constructor of a derived class.", - "start": 137, - "length": 4, - "category": "error", - "code": 17009 } ]`); \ No newline at end of file From 9e00df590d638cad1266e388385396aea2879cc3 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Fri, 6 Oct 2017 19:46:29 -0700 Subject: [PATCH 068/246] Error when accessing abstract property in constructor #9230 --- src/compiler/checker.ts | 28 ++++++++-- src/compiler/diagnosticMessages.json | 4 ++ .../abstractPropertyInConstructor.errors.txt | 25 +++++++++ .../abstractPropertyInConstructor.js | 30 ++++++++++ .../abstractPropertyInConstructor.symbols | 48 ++++++++++++++++ .../abstractPropertyInConstructor.types | 56 +++++++++++++++++++ .../compiler/abstractPropertyInConstructor.ts | 15 +++++ 7 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/abstractPropertyInConstructor.errors.txt create mode 100644 tests/baselines/reference/abstractPropertyInConstructor.js create mode 100644 tests/baselines/reference/abstractPropertyInConstructor.symbols create mode 100644 tests/baselines/reference/abstractPropertyInConstructor.types create mode 100644 tests/cases/compiler/abstractPropertyInConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8e18c432a6bb..9a483ae50ed27 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14826,11 +14826,7 @@ namespace ts { // where this references the constructor function object of a derived class, // a super property access is permitted and must specify a public static member function of the base class. if (languageVersion < ScriptTarget.ES2015) { - const hasNonMethodDeclaration = forEachProperty(prop, p => { - const propKind = getDeclarationKindFromSymbol(p); - return propKind !== SyntaxKind.MethodDeclaration && propKind !== SyntaxKind.MethodSignature; - }); - if (hasNonMethodDeclaration) { + if (symbolHasNonMethodDeclaration(prop)) { error(errorNode, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); return false; } @@ -14845,6 +14841,17 @@ namespace ts { } } + // Referencing Abstract Properties within Constructors is not allowed + if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop)) { + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); + const declaringClassConstructor = declaringClassDeclaration && findConstructorDeclaration(declaringClassDeclaration); + + if (declaringClassConstructor && isNodeWithinFunction(node, declaringClassConstructor)) { + error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_constructor, symbolToString(prop), typeToString(getDeclaringClass(prop))); + return false; + } + } + // Public properties are otherwise accessible. if (!(flags & ModifierFlags.NonPublicAccessibilityModifier)) { return true; @@ -14896,6 +14903,13 @@ namespace ts { return true; } + function symbolHasNonMethodDeclaration(symbol: Symbol) { + return forEachProperty(symbol, prop => { + const propKind = getDeclarationKindFromSymbol(prop); + return propKind !== SyntaxKind.MethodDeclaration && propKind !== SyntaxKind.MethodSignature; + }); + } + function checkNonNullExpression(node: Expression | QualifiedName) { return checkNonNullType(checkExpression(node), node); } @@ -23139,6 +23153,10 @@ namespace ts { return result; } + function isNodeWithinFunction(node: Node, functionDeclaration: FunctionLike) { + return getContainingFunction(node) === functionDeclaration; + } + function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { return !!forEachEnclosingClass(node, n => n === classDeclaration); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f3d6d4fcc4706..e2d514ba268e5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2220,6 +2220,10 @@ "category": "Error", "code": 2714 }, + "Abstract property '{0}' in class '{1}' cannot be accessed in constructor.": { + "category": "Error", + "code": 2715 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt new file mode 100644 index 0000000000000..7e654b440c643 --- /dev/null +++ b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/abstractPropertyInConstructor.ts(4,24): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. +tests/cases/compiler/abstractPropertyInConstructor.ts(5,14): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. + + +==== tests/cases/compiler/abstractPropertyInConstructor.ts (2 errors) ==== + abstract class AbstractClass { + constructor(str: string) { + this.method(parseInt(str)); + let val = this.prop.toLowerCase(); + ~~~~ +!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. + this.prop = "Hello World"; + ~~~~ +!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. + } + + abstract prop: string; + + abstract method(num: number): void; + + method2() { + this.prop = this.prop + "!"; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/abstractPropertyInConstructor.js b/tests/baselines/reference/abstractPropertyInConstructor.js new file mode 100644 index 0000000000000..c6d7de6c0374e --- /dev/null +++ b/tests/baselines/reference/abstractPropertyInConstructor.js @@ -0,0 +1,30 @@ +//// [abstractPropertyInConstructor.ts] +abstract class AbstractClass { + constructor(str: string) { + this.method(parseInt(str)); + let val = this.prop.toLowerCase(); + this.prop = "Hello World"; + } + + abstract prop: string; + + abstract method(num: number): void; + + method2() { + this.prop = this.prop + "!"; + } +} + + +//// [abstractPropertyInConstructor.js] +var AbstractClass = /** @class */ (function () { + function AbstractClass(str) { + this.method(parseInt(str)); + var val = this.prop.toLowerCase(); + this.prop = "Hello World"; + } + AbstractClass.prototype.method2 = function () { + this.prop = this.prop + "!"; + }; + return AbstractClass; +}()); diff --git a/tests/baselines/reference/abstractPropertyInConstructor.symbols b/tests/baselines/reference/abstractPropertyInConstructor.symbols new file mode 100644 index 0000000000000..7d634f802672a --- /dev/null +++ b/tests/baselines/reference/abstractPropertyInConstructor.symbols @@ -0,0 +1,48 @@ +=== tests/cases/compiler/abstractPropertyInConstructor.ts === +abstract class AbstractClass { +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) + + constructor(str: string) { +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) + + this.method(parseInt(str)); +>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) +>parseInt : Symbol(parseInt, Decl(lib.d.ts, --, --)) +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) + + let val = this.prop.toLowerCase(); +>val : Symbol(val, Decl(abstractPropertyInConstructor.ts, 3, 11)) +>this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) + + this.prop = "Hello World"; +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) + } + + abstract prop: string; +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) + + abstract method(num: number): void; +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) +>num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 9, 20)) + + method2() { +>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 9, 39)) + + this.prop = this.prop + "!"; +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) + } +} + diff --git a/tests/baselines/reference/abstractPropertyInConstructor.types b/tests/baselines/reference/abstractPropertyInConstructor.types new file mode 100644 index 0000000000000..05f7a7752e622 --- /dev/null +++ b/tests/baselines/reference/abstractPropertyInConstructor.types @@ -0,0 +1,56 @@ +=== tests/cases/compiler/abstractPropertyInConstructor.ts === +abstract class AbstractClass { +>AbstractClass : AbstractClass + + constructor(str: string) { +>str : string + + this.method(parseInt(str)); +>this.method(parseInt(str)) : void +>this.method : (num: number) => void +>this : this +>method : (num: number) => void +>parseInt(str) : number +>parseInt : (s: string, radix?: number) => number +>str : string + + let val = this.prop.toLowerCase(); +>val : string +>this.prop.toLowerCase() : string +>this.prop.toLowerCase : () => string +>this.prop : string +>this : this +>prop : string +>toLowerCase : () => string + + this.prop = "Hello World"; +>this.prop = "Hello World" : "Hello World" +>this.prop : string +>this : this +>prop : string +>"Hello World" : "Hello World" + } + + abstract prop: string; +>prop : string + + abstract method(num: number): void; +>method : (num: number) => void +>num : number + + method2() { +>method2 : () => void + + this.prop = this.prop + "!"; +>this.prop = this.prop + "!" : string +>this.prop : string +>this : this +>prop : string +>this.prop + "!" : string +>this.prop : string +>this : this +>prop : string +>"!" : "!" + } +} + diff --git a/tests/cases/compiler/abstractPropertyInConstructor.ts b/tests/cases/compiler/abstractPropertyInConstructor.ts new file mode 100644 index 0000000000000..5376aae9d6f55 --- /dev/null +++ b/tests/cases/compiler/abstractPropertyInConstructor.ts @@ -0,0 +1,15 @@ +abstract class AbstractClass { + constructor(str: string) { + this.method(parseInt(str)); + let val = this.prop.toLowerCase(); + this.prop = "Hello World"; + } + + abstract prop: string; + + abstract method(num: number): void; + + method2() { + this.prop = this.prop + "!"; + } +} From 8a55baf9a3caf88c7e89e563ec51466644981df4 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 9 Oct 2017 09:58:02 -0700 Subject: [PATCH 069/246] In @typedef tag, handle property with no type (#19013) --- src/compiler/binder.ts | 2 +- src/compiler/parser.ts | 2 +- src/compiler/types.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- .../jsdocTypedef_propertyWithNoType.symbols | 11 +++++++++++ .../reference/jsdocTypedef_propertyWithNoType.types | 13 +++++++++++++ .../compiler/jsdocTypedef_propertyWithNoType.ts | 12 ++++++++++++ 8 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/jsdocTypedef_propertyWithNoType.symbols create mode 100644 tests/baselines/reference/jsdocTypedef_propertyWithNoType.types create mode 100644 tests/cases/compiler/jsdocTypedef_propertyWithNoType.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 28193535ce9a2..9b977eb6bfcd1 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2146,7 +2146,7 @@ namespace ts { // falls through case SyntaxKind.JSDocPropertyTag: const propTag = node as JSDocPropertyLikeTag; - const flags = propTag.isBracketed || propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? + const flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property; return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ebdf390f5b262..db6c5f23cfdda 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6699,7 +6699,7 @@ namespace ts { if (typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType) { jsdocTypeLiteral.isArrayType = true; } - typedefTag.typeExpression = childTypeTag && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? + typedefTag.typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? childTypeTag.typeExpression : finishNode(jsdocTypeLiteral); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 578c2d23c4f39..f1d4740ccac05 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2194,7 +2194,7 @@ namespace ts { export interface JSDocPropertyLikeTag extends JSDocTag, Declaration { parent: JSDoc; name: EntityName; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ isNameFirst: boolean; isBracketed: boolean; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 3bb2ed1167488..7fe07813adcc5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1473,7 +1473,7 @@ declare namespace ts { interface JSDocPropertyLikeTag extends JSDocTag, Declaration { parent: JSDoc; name: EntityName; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ isNameFirst: boolean; isBracketed: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index d41db2eb413ee..a5bb674d511e7 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1473,7 +1473,7 @@ declare namespace ts { interface JSDocPropertyLikeTag extends JSDocTag, Declaration { parent: JSDoc; name: EntityName; - typeExpression: JSDocTypeExpression; + typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ isNameFirst: boolean; isBracketed: boolean; diff --git a/tests/baselines/reference/jsdocTypedef_propertyWithNoType.symbols b/tests/baselines/reference/jsdocTypedef_propertyWithNoType.symbols new file mode 100644 index 0000000000000..0bac06e2e6114 --- /dev/null +++ b/tests/baselines/reference/jsdocTypedef_propertyWithNoType.symbols @@ -0,0 +1,11 @@ +=== /a.js === +/** + * @typedef Foo + * @property foo + */ + +/** @type {Foo} */ +const x = { foo: 0 }; +>x : Symbol(x, Decl(a.js, 6, 5)) +>foo : Symbol(foo, Decl(a.js, 6, 11)) + diff --git a/tests/baselines/reference/jsdocTypedef_propertyWithNoType.types b/tests/baselines/reference/jsdocTypedef_propertyWithNoType.types new file mode 100644 index 0000000000000..7d7326fc80c7b --- /dev/null +++ b/tests/baselines/reference/jsdocTypedef_propertyWithNoType.types @@ -0,0 +1,13 @@ +=== /a.js === +/** + * @typedef Foo + * @property foo + */ + +/** @type {Foo} */ +const x = { foo: 0 }; +>x : { foo: any; } +>{ foo: 0 } : { foo: number; } +>foo : number +>0 : 0 + diff --git a/tests/cases/compiler/jsdocTypedef_propertyWithNoType.ts b/tests/cases/compiler/jsdocTypedef_propertyWithNoType.ts new file mode 100644 index 0000000000000..bcabe980915d0 --- /dev/null +++ b/tests/cases/compiler/jsdocTypedef_propertyWithNoType.ts @@ -0,0 +1,12 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @Filename: /a.js +/** + * @typedef Foo + * @property foo + */ + +/** @type {Foo} */ +const x = { foo: 0 }; From 79f5d968a120e469dbaf432aaad101a708989a6d Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Mon, 9 Oct 2017 10:57:08 -0700 Subject: [PATCH 070/246] Use ancestor walk to determine if property access is within constructor #9230 --- src/compiler/checker.ts | 17 ++++-- src/compiler/diagnosticMessages.json | 2 +- .../abstractPropertyInConstructor.errors.txt | 26 +++++++--- .../abstractPropertyInConstructor.js | 20 ++++++- .../abstractPropertyInConstructor.symbols | 52 +++++++++++++------ .../abstractPropertyInConstructor.types | 27 +++++++++- .../compiler/abstractPropertyInConstructor.ts | 11 +++- 7 files changed, 123 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9a483ae50ed27..8afee9455cfa9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14844,10 +14844,9 @@ namespace ts { // Referencing Abstract Properties within Constructors is not allowed if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop)) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); - const declaringClassConstructor = declaringClassDeclaration && findConstructorDeclaration(declaringClassDeclaration); - if (declaringClassConstructor && isNodeWithinFunction(node, declaringClassConstructor)) { - error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_constructor, symbolToString(prop), typeToString(getDeclaringClass(prop))); + if (declaringClassDeclaration && isNodeWithinConstructor(node, declaringClassDeclaration)) { + error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), typeToString(getDeclaringClass(prop))); return false; } } @@ -23153,8 +23152,16 @@ namespace ts { return result; } - function isNodeWithinFunction(node: Node, functionDeclaration: FunctionLike) { - return getContainingFunction(node) === functionDeclaration; + function isNodeWithinConstructor(node: Node, classDeclaration: ClassLikeDeclaration) { + return findAncestor(node, element => { + if (isConstructorDeclaration(element) && nodeIsPresent(element.body)) { + return true; + } else if (element === classDeclaration || isFunctionLikeDeclaration(element)) { + return "quit"; + } + + return false; + }); } function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e2d514ba268e5..9b220a880b0b7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2220,7 +2220,7 @@ "category": "Error", "code": 2714 }, - "Abstract property '{0}' in class '{1}' cannot be accessed in constructor.": { + "Abstract property '{0}' in class '{1}' cannot be accessed in the constructor.": { "category": "Error", "code": 2715 }, diff --git a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt index 7e654b440c643..461dd713d3b11 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt +++ b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt @@ -1,20 +1,32 @@ -tests/cases/compiler/abstractPropertyInConstructor.ts(4,24): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. -tests/cases/compiler/abstractPropertyInConstructor.ts(5,14): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. +tests/cases/compiler/abstractPropertyInConstructor.ts(4,24): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. +tests/cases/compiler/abstractPropertyInConstructor.ts(7,18): error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. +tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor. -==== tests/cases/compiler/abstractPropertyInConstructor.ts (2 errors) ==== +==== tests/cases/compiler/abstractPropertyInConstructor.ts (3 errors) ==== abstract class AbstractClass { constructor(str: string) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); ~~~~ -!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. - this.prop = "Hello World"; - ~~~~ -!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in constructor. +!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. + + if (!str) { + this.prop = "Hello World"; + ~~~~ +!!! error TS2715: Abstract property 'prop' in class 'AbstractClass' cannot be accessed in the constructor. + } + this.cb(str); + ~~ +!!! error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor. + + const innerFunction = () => { + return this.prop; + } } abstract prop: string; + abstract cb: (s: string) => void; abstract method(num: number): void; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.js b/tests/baselines/reference/abstractPropertyInConstructor.js index c6d7de6c0374e..18a2937a1911f 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.js +++ b/tests/baselines/reference/abstractPropertyInConstructor.js @@ -3,10 +3,19 @@ abstract class AbstractClass { constructor(str: string) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); - this.prop = "Hello World"; + + if (!str) { + this.prop = "Hello World"; + } + this.cb(str); + + const innerFunction = () => { + return this.prop; + } } abstract prop: string; + abstract cb: (s: string) => void; abstract method(num: number): void; @@ -19,9 +28,16 @@ abstract class AbstractClass { //// [abstractPropertyInConstructor.js] var AbstractClass = /** @class */ (function () { function AbstractClass(str) { + var _this = this; this.method(parseInt(str)); var val = this.prop.toLowerCase(); - this.prop = "Hello World"; + if (!str) { + this.prop = "Hello World"; + } + this.cb(str); + var innerFunction = function () { + return _this.prop; + }; } AbstractClass.prototype.method2 = function () { this.prop = this.prop + "!"; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.symbols b/tests/baselines/reference/abstractPropertyInConstructor.symbols index 7d634f802672a..0d542ffb0a8cc 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.symbols +++ b/tests/baselines/reference/abstractPropertyInConstructor.symbols @@ -6,43 +6,65 @@ abstract class AbstractClass { >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) this.method(parseInt(str)); ->this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) +>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) >parseInt : Symbol(parseInt, Decl(lib.d.ts, --, --)) >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) let val = this.prop.toLowerCase(); >val : Symbol(val, Decl(abstractPropertyInConstructor.ts, 3, 11)) >this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) >toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) - this.prop = "Hello World"; ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) + if (!str) { +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) + + this.prop = "Hello World"; +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) + } + this.cb(str); +>this.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) + + const innerFunction = () => { +>innerFunction : Symbol(innerFunction, Decl(abstractPropertyInConstructor.ts, 10, 13)) + + return this.prop; +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) + } } abstract prop: string; ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) + + abstract cb: (s: string) => void; +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 16, 18)) abstract method(num: number): void; ->method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 7, 26)) ->num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 9, 20)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) +>num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 18, 20)) method2() { ->method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 9, 39)) +>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) this.prop = this.prop + "!"; ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 5, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) } } diff --git a/tests/baselines/reference/abstractPropertyInConstructor.types b/tests/baselines/reference/abstractPropertyInConstructor.types index 05f7a7752e622..0ffb5f1bdfd67 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.types +++ b/tests/baselines/reference/abstractPropertyInConstructor.types @@ -23,17 +23,42 @@ abstract class AbstractClass { >prop : string >toLowerCase : () => string - this.prop = "Hello World"; + if (!str) { +>!str : boolean +>str : string + + this.prop = "Hello World"; >this.prop = "Hello World" : "Hello World" >this.prop : string >this : this >prop : string >"Hello World" : "Hello World" + } + this.cb(str); +>this.cb(str) : void +>this.cb : (s: string) => void +>this : this +>cb : (s: string) => void +>str : string + + const innerFunction = () => { +>innerFunction : () => string +>() => { return this.prop; } : () => string + + return this.prop; +>this.prop : string +>this : this +>prop : string + } } abstract prop: string; >prop : string + abstract cb: (s: string) => void; +>cb : (s: string) => void +>s : string + abstract method(num: number): void; >method : (num: number) => void >num : number diff --git a/tests/cases/compiler/abstractPropertyInConstructor.ts b/tests/cases/compiler/abstractPropertyInConstructor.ts index 5376aae9d6f55..457fdb473b1b8 100644 --- a/tests/cases/compiler/abstractPropertyInConstructor.ts +++ b/tests/cases/compiler/abstractPropertyInConstructor.ts @@ -2,10 +2,19 @@ abstract class AbstractClass { constructor(str: string) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); - this.prop = "Hello World"; + + if (!str) { + this.prop = "Hello World"; + } + this.cb(str); + + const innerFunction = () => { + return this.prop; + } } abstract prop: string; + abstract cb: (s: string) => void; abstract method(num: number): void; From 2796ebfe35ca08518ed196b522181bc0deff2373 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 9 Oct 2017 11:04:28 -0700 Subject: [PATCH 071/246] In resolveNameHelper, use a lastNonBlockLocation (#18918) --- src/compiler/checker.ts | 6 ++- .../noUnusedLocals_selfReference.errors.txt | 16 ++++-- .../reference/noUnusedLocals_selfReference.js | 14 ++++- .../noUnusedLocals_selfReference.symbols | 51 +++++++++++-------- .../noUnusedLocals_selfReference.types | 11 +++- .../compiler/noUnusedLocals_selfReference.ts | 7 ++- 6 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8e18c432a6bb..58ac3bc52c0bc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -908,6 +908,7 @@ namespace ts { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location let result: Symbol; let lastLocation: Node; + let lastNonBlockLocation: Node; let propertyWithInvalidInitializer: Node; const errorLocation = location; let grandparent: Node; @@ -1126,6 +1127,9 @@ namespace ts { } break; } + if (location.kind !== SyntaxKind.Block) { + lastNonBlockLocation = location; + } lastLocation = location; location = location.parent; } @@ -1133,7 +1137,7 @@ namespace ts { // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. // If `result === lastLocation.symbol`, that means that we are somewhere inside `lastLocation` looking up a name, and resolving to `lastLocation` itself. // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. - if (isUse && result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastLocation.symbol) { + if (isUse && result && nameNotFoundMessage && noUnusedIdentifiers && result !== lastNonBlockLocation.symbol) { result.isReferenced = true; } diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt index e4a0d478cb4fb..603bc54d4481a 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt +++ b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt @@ -1,14 +1,22 @@ tests/cases/compiler/noUnusedLocals_selfReference.ts(3,10): error TS6133: 'f' is declared but its value is never read. -tests/cases/compiler/noUnusedLocals_selfReference.ts(4,7): error TS6133: 'C' is declared but its value is never read. -tests/cases/compiler/noUnusedLocals_selfReference.ts(7,6): error TS6133: 'E' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(5,14): error TS6133: 'g' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(9,7): error TS6133: 'C' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(12,6): error TS6133: 'E' is declared but its value is never read. -==== tests/cases/compiler/noUnusedLocals_selfReference.ts (3 errors) ==== +==== tests/cases/compiler/noUnusedLocals_selfReference.ts (4 errors) ==== export {}; // Make this a module scope, so these are local variables. - function f() { f; } + function f() { ~ !!! error TS6133: 'f' is declared but its value is never read. + f; + function g() { + ~ +!!! error TS6133: 'g' is declared but its value is never read. + g; + } + } class C { ~ !!! error TS6133: 'C' is declared but its value is never read. diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.js b/tests/baselines/reference/noUnusedLocals_selfReference.js index 5f206fbc3dc46..a8f3d6a8aedf6 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.js +++ b/tests/baselines/reference/noUnusedLocals_selfReference.js @@ -1,7 +1,12 @@ //// [noUnusedLocals_selfReference.ts] export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { + f; + function g() { + g; + } +} class C { m() { C; } } @@ -19,7 +24,12 @@ P; //// [noUnusedLocals_selfReference.js] "use strict"; exports.__esModule = true; -function f() { f; } +function f() { + f; + function g() { + g; + } +} var C = /** @class */ (function () { function C() { } diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.symbols b/tests/baselines/reference/noUnusedLocals_selfReference.symbols index dcd815b261992..015a78d87d3f5 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.symbols +++ b/tests/baselines/reference/noUnusedLocals_selfReference.symbols @@ -1,43 +1,52 @@ === tests/cases/compiler/noUnusedLocals_selfReference.ts === export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { >f : Symbol(f, Decl(noUnusedLocals_selfReference.ts, 0, 10)) + + f; >f : Symbol(f, Decl(noUnusedLocals_selfReference.ts, 0, 10)) + function g() { +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 3, 6)) + + g; +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 3, 6)) + } +} class C { ->C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 2, 19)) +>C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 7, 1)) m() { C; } ->m : Symbol(C.m, Decl(noUnusedLocals_selfReference.ts, 3, 9)) ->C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 2, 19)) +>m : Symbol(C.m, Decl(noUnusedLocals_selfReference.ts, 8, 9)) +>C : Symbol(C, Decl(noUnusedLocals_selfReference.ts, 7, 1)) } enum E { A = 0, B = E.A } ->E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 5, 1)) ->A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) ->B : Symbol(E.B, Decl(noUnusedLocals_selfReference.ts, 6, 15)) ->E.A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) ->E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 5, 1)) ->A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 6, 8)) +>E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 10, 1)) +>A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) +>B : Symbol(E.B, Decl(noUnusedLocals_selfReference.ts, 11, 15)) +>E.A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) +>E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 10, 1)) +>A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) // Does not detect mutual recursion. function g() { D; } ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 6, 25)) ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 9, 19)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) class D { m() { g; } } ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 9, 19)) ->m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 10, 9)) ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 6, 25)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) +>m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 15, 9)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) // Does not work on private methods. class P { private m() { this.m; } } ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) ->this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) ->this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) +>this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) +>this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) P; ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 10, 22)) +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.types b/tests/baselines/reference/noUnusedLocals_selfReference.types index 7d2741c5681a1..7e75062db34d5 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.types +++ b/tests/baselines/reference/noUnusedLocals_selfReference.types @@ -1,10 +1,19 @@ === tests/cases/compiler/noUnusedLocals_selfReference.ts === export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { >f : () => void + + f; >f : () => void + function g() { +>g : () => void + + g; +>g : () => void + } +} class C { >C : C diff --git a/tests/cases/compiler/noUnusedLocals_selfReference.ts b/tests/cases/compiler/noUnusedLocals_selfReference.ts index 8eb528743c0ba..fc6b02b600634 100644 --- a/tests/cases/compiler/noUnusedLocals_selfReference.ts +++ b/tests/cases/compiler/noUnusedLocals_selfReference.ts @@ -2,7 +2,12 @@ export {}; // Make this a module scope, so these are local variables. -function f() { f; } +function f() { + f; + function g() { + g; + } +} class C { m() { C; } } From 517dbf3ca77863daa5376dfb4a95088d1f0dffab Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 9 Oct 2017 11:14:24 -0700 Subject: [PATCH 072/246] Fix semicolon lint --- 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 d7585bd6e9a80..a61ded007f449 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13923,7 +13923,7 @@ namespace ts { t.flags |= propagatedFlags; t.flags |= TypeFlags.FreshLiteral; (t as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; - t.symbol = node.symbol + t.symbol = node.symbol; } }); return spread; From 8486c482371e800fcaa83c655f837f70d8ac02af Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Mon, 9 Oct 2017 13:01:30 -0700 Subject: [PATCH 073/246] Fix linting error in new function --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8afee9455cfa9..26e851eb53da1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23156,7 +23156,8 @@ namespace ts { return findAncestor(node, element => { if (isConstructorDeclaration(element) && nodeIsPresent(element.body)) { return true; - } else if (element === classDeclaration || isFunctionLikeDeclaration(element)) { + } + else if (element === classDeclaration || isFunctionLikeDeclaration(element)) { return "quit"; } From 264652c0ef7197116280af77c284b124071eb661 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 9 Oct 2017 13:12:27 -0700 Subject: [PATCH 074/246] Fix emit for classes with both fields and 'extends null' --- src/compiler/transformers/ts.ts | 28 +++++++++---------- .../baselines/reference/classExtendingNull.js | 17 ++++++++++- .../reference/classExtendingNull.symbols | 8 ++++++ .../reference/classExtendingNull.types | 13 +++++++++ .../classDeclarations/classExtendingNull.ts | 2 ++ 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 4feb3ca0c262f..e67918fd696a4 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -26,7 +26,7 @@ namespace ts { IsExportOfNamespace = 1 << 3, IsNamedExternalExport = 1 << 4, IsDefaultExternalExport = 1 << 5, - HasExtendsClause = 1 << 6, + IsDerivedClass = 1 << 6, UseImmediatelyInvokedFunctionExpression = 1 << 7, HasAnyDecorators = HasConstructorDecorators | HasMemberDecorators, @@ -553,7 +553,8 @@ namespace ts { function getClassFacts(node: ClassDeclaration, staticProperties: ReadonlyArray) { let facts = ClassFacts.None; if (some(staticProperties)) facts |= ClassFacts.HasStaticInitializedProperties; - if (getClassExtendsHeritageClauseElement(node)) facts |= ClassFacts.HasExtendsClause; + const extendsClauseElement = getClassExtendsHeritageClauseElement(node); + if (extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword) facts |= ClassFacts.IsDerivedClass; if (shouldEmitDecorateCallForClass(node)) facts |= ClassFacts.HasConstructorDecorators; if (childIsDecorated(node)) facts |= ClassFacts.HasMemberDecorators; if (isExportOfNamespace(node)) facts |= ClassFacts.IsExportOfNamespace; @@ -699,7 +700,7 @@ namespace ts { name, /*typeParameters*/ undefined, visitNodes(node.heritageClauses, visitor, isHeritageClause), - transformClassMembers(node, (facts & ClassFacts.HasExtendsClause) !== 0) + transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0) ); // To better align with the old emitter, we should not emit a trailing source map @@ -814,7 +815,7 @@ namespace ts { // ${members} // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); - const members = transformClassMembers(node, (facts & ClassFacts.HasExtendsClause) !== 0); + const members = transformClassMembers(node, (facts & ClassFacts.IsDerivedClass) !== 0); const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); setOriginalNode(classExpression, node); setTextRange(classExpression, location); @@ -887,11 +888,11 @@ namespace ts { * Transforms the members of a class. * * @param node The current class. - * @param hasExtendsClause A value indicating whether the class has an extends clause. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformClassMembers(node: ClassDeclaration | ClassExpression, hasExtendsClause: boolean) { + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { const members: ClassElement[] = []; - const constructor = transformConstructor(node, hasExtendsClause); + const constructor = transformConstructor(node, isDerivedClass); if (constructor) { members.push(constructor); } @@ -904,9 +905,9 @@ namespace ts { * Transforms (or creates) a constructor for a class. * * @param node The current class. - * @param hasExtendsClause A value indicating whether the class has an extends clause. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformConstructor(node: ClassDeclaration | ClassExpression, hasExtendsClause: boolean) { + function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { // Check if we have property assignment inside class declaration. // If there is a property assignment, we need to emit constructor whether users define it or not // If there is no property assignment, we can omit constructor if users do not define it @@ -921,7 +922,7 @@ namespace ts { } const parameters = transformConstructorParameters(constructor); - const body = transformConstructorBody(node, constructor, hasExtendsClause); + const body = transformConstructorBody(node, constructor, isDerivedClass); // constructor(${parameters}) { // ${body} @@ -947,7 +948,6 @@ namespace ts { * parameter property assignments or instance property initializers. * * @param constructor The constructor declaration. - * @param hasExtendsClause A value indicating whether the class has an extends clause. */ function transformConstructorParameters(constructor: ConstructorDeclaration) { // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: @@ -975,9 +975,9 @@ namespace ts { * * @param node The current class. * @param constructor The current class constructor. - * @param hasExtendsClause A value indicating whether the class has an extends clause. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. */ - function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean) { + function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, isDerivedClass: boolean) { let statements: Statement[] = []; let indexOfFirstStatement = 0; @@ -1001,7 +1001,7 @@ namespace ts { const propertyAssignments = getParametersWithPropertyAssignments(constructor); addRange(statements, map(propertyAssignments, transformParameterWithPropertyAssignment)); } - else if (hasExtendsClause) { + else if (isDerivedClass) { // Add a synthetic `super` call: // // super(...arguments); diff --git a/tests/baselines/reference/classExtendingNull.js b/tests/baselines/reference/classExtendingNull.js index 6c6ae8a016720..f405f6da84c2d 100644 --- a/tests/baselines/reference/classExtendingNull.js +++ b/tests/baselines/reference/classExtendingNull.js @@ -1,7 +1,8 @@ //// [classExtendingNull.ts] class C1 extends null { } class C2 extends (null) { } - +class C3 extends null { x = 1; } +class C4 extends (null) { x = 1; } //// [classExtendingNull.js] var __extends = (this && this.__extends) || (function () { @@ -26,3 +27,17 @@ var C2 = /** @class */ (function (_super) { } return C2; }((null))); +var C3 = /** @class */ (function (_super) { + __extends(C3, _super); + function C3() { + this.x = 1; + } + return C3; +}(null)); +var C4 = /** @class */ (function (_super) { + __extends(C4, _super); + function C4() { + this.x = 1; + } + return C4; +}((null))); diff --git a/tests/baselines/reference/classExtendingNull.symbols b/tests/baselines/reference/classExtendingNull.symbols index 37a6162f41478..eff1f18c0cad2 100644 --- a/tests/baselines/reference/classExtendingNull.symbols +++ b/tests/baselines/reference/classExtendingNull.symbols @@ -5,3 +5,11 @@ class C1 extends null { } class C2 extends (null) { } >C2 : Symbol(C2, Decl(classExtendingNull.ts, 0, 25)) +class C3 extends null { x = 1; } +>C3 : Symbol(C3, Decl(classExtendingNull.ts, 1, 27)) +>x : Symbol(C3.x, Decl(classExtendingNull.ts, 2, 23)) + +class C4 extends (null) { x = 1; } +>C4 : Symbol(C4, Decl(classExtendingNull.ts, 2, 32)) +>x : Symbol(C4.x, Decl(classExtendingNull.ts, 3, 25)) + diff --git a/tests/baselines/reference/classExtendingNull.types b/tests/baselines/reference/classExtendingNull.types index 3c572a3406ced..e98f8daba063c 100644 --- a/tests/baselines/reference/classExtendingNull.types +++ b/tests/baselines/reference/classExtendingNull.types @@ -8,3 +8,16 @@ class C2 extends (null) { } >(null) : null >null : null +class C3 extends null { x = 1; } +>C3 : C3 +>null : null +>x : number +>1 : 1 + +class C4 extends (null) { x = 1; } +>C4 : C4 +>(null) : null +>null : null +>x : number +>1 : 1 + diff --git a/tests/cases/conformance/classes/classDeclarations/classExtendingNull.ts b/tests/cases/conformance/classes/classDeclarations/classExtendingNull.ts index 655cf44ed5779..b00c047a3799b 100644 --- a/tests/cases/conformance/classes/classDeclarations/classExtendingNull.ts +++ b/tests/cases/conformance/classes/classDeclarations/classExtendingNull.ts @@ -1,2 +1,4 @@ class C1 extends null { } class C2 extends (null) { } +class C3 extends null { x = 1; } +class C4 extends (null) { x = 1; } \ No newline at end of file From 8b60736b61b8559fc7bd542a5e8954e258f51bd3 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 9 Oct 2017 13:39:15 -0700 Subject: [PATCH 075/246] importFixes: Remove unnecessary undefined check (#19045) --- src/services/codefixes/importFixes.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index f516bc15de3ab..9b54543231dd4 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -16,7 +16,7 @@ namespace ts.codefix { moduleSpecifier?: string; } - enum ModuleSpecifierComparison { + const enum ModuleSpecifierComparison { Better, Equal, Worse @@ -26,10 +26,6 @@ namespace ts.codefix { private symbolIdToActionMap: ImportCodeAction[][] = []; addAction(symbolId: number, newAction: ImportCodeAction) { - if (!newAction) { - return; - } - const actions = this.symbolIdToActionMap[symbolId]; if (!actions) { this.symbolIdToActionMap[symbolId] = [newAction]; From 07ba90659404830f735f819b645476954c3c5d9a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 9 Oct 2017 14:25:48 -0700 Subject: [PATCH 076/246] Handle the case when finishCachingPerDirectoryResolution is not called because of exception Fixes #18975 --- src/compiler/resolutionCache.ts | 10 ++++++++-- src/compiler/watch.ts | 10 +++++----- src/server/project.ts | 7 +++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index aecc698989134..680ed98a84a4f 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -141,7 +141,10 @@ namespace ts { resolvedModuleNames.clear(); resolvedTypeReferenceDirectives.clear(); allFilesHaveInvalidatedResolution = false; - Debug.assert(perDirectoryResolvedModuleNames.size === 0 && perDirectoryResolvedTypeReferenceDirectives.size === 0); + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) + perDirectoryResolvedModuleNames.clear(); + perDirectoryResolvedTypeReferenceDirectives.clear(); } function startRecordingFilesWithChangedResolutions() { @@ -166,7 +169,10 @@ namespace ts { } function startCachingPerDirectoryResolution() { - Debug.assert(perDirectoryResolvedModuleNames.size === 0 && perDirectoryResolvedTypeReferenceDirectives.size === 0); + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) + perDirectoryResolvedModuleNames.clear(); + perDirectoryResolvedTypeReferenceDirectives.clear(); } function finishCachingPerDirectoryResolution() { diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 2ab3ccc5ce65d..1ab80e659f42d 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -322,6 +322,9 @@ namespace ts { if (hasChangedCompilerOptions) { newLine = getNewLineCharacter(compilerOptions, system); + if (changesAffectModuleResolution(program && program.getCompilerOptions(), compilerOptions)) { + resolutionCache.clear(); + } } const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(); @@ -329,14 +332,11 @@ namespace ts { return; } - if (hasChangedCompilerOptions && changesAffectModuleResolution(program && program.getCompilerOptions(), compilerOptions)) { - resolutionCache.clear(); - } - const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !program; - hasChangedCompilerOptions = false; beforeCompile(compilerOptions); // Compile the program + const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !program; + hasChangedCompilerOptions = false; resolutionCache.startCachingPerDirectoryResolution(); compilerHost.hasInvalidatedResolution = hasInvalidatedResolution; compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; diff --git a/src/server/project.ts b/src/server/project.ts index ac18738027b65..5132b82a804fd 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -229,8 +229,8 @@ namespace ts.server { this.realpath = path => host.realpath(path); } - this.languageService = createLanguageService(this, this.documentRegistry); this.resolutionCache = createResolutionCache(this, rootDirectoryForResolution); + this.languageService = createLanguageService(this, this.documentRegistry); if (!languageServiceEnabled) { this.disableLanguageService(); } @@ -732,7 +732,6 @@ namespace ts.server { */ updateGraph(): boolean { this.resolutionCache.startRecordingFilesWithChangedResolutions(); - this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(); let hasChanges = this.updateGraphWorker(); @@ -795,6 +794,7 @@ namespace ts.server { this.writeLog(`Starting updateGraphWorker: Project: ${this.getProjectName()}`); const start = timestamp(); + this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(); this.resolutionCache.startCachingPerDirectoryResolution(); this.program = this.languageService.getProgram(); this.resolutionCache.finishCachingPerDirectoryResolution(); @@ -1327,14 +1327,13 @@ namespace ts.server { } close() { - super.close(); - if (this.configFileWatcher) { this.configFileWatcher.close(); this.configFileWatcher = undefined; } this.stopWatchingWildCards(); + super.close(); } addOpenRef() { From 5f3d6e753e0c89419bd3734ccf991c26ba772131 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 9 Oct 2017 14:43:51 -0700 Subject: [PATCH 077/246] update baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 ++ tests/baselines/reference/api/typescript.d.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ca8696b11fb8d..5f4ef1dbdfec4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2870,6 +2870,8 @@ declare namespace ts { function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node: Node): ReadonlyArray | undefined; + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ + function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray | undefined; } declare namespace ts { function isNumericLiteral(node: Node): node is NumericLiteral; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 820be44f1f1c4..e608c7ffc3d1e 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2925,6 +2925,8 @@ declare namespace ts { function getJSDocReturnType(node: Node): TypeNode | undefined; /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node: Node): ReadonlyArray | undefined; + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ + function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray | undefined; } declare namespace ts { function isNumericLiteral(node: Node): node is NumericLiteral; From bb3467b8e1c2b7897bc30e282e59bd85a8b8c714 Mon Sep 17 00:00:00 2001 From: Joe Calzaretta Date: Mon, 9 Oct 2017 17:58:41 -0400 Subject: [PATCH 078/246] Handle type guard predicates on `Array.find` (#18160) * Handle type guard predicates on `Array.find` If the `predicate` function passed to `Array.find` or `ReadonlyArray.find` is a type guard narrowing `value` to type `S`, then any returned element should also be narrowed to `S`. Adding test case and associated baselines * trailing whitespace after merge conflict --- src/lib/es2015.core.d.ts | 2 + tests/baselines/reference/arrayFind.js | 22 ++++++++++ tests/baselines/reference/arrayFind.symbols | 33 +++++++++++++++ tests/baselines/reference/arrayFind.types | 46 +++++++++++++++++++++ tests/cases/compiler/arrayFind.ts | 12 ++++++ 5 files changed, 115 insertions(+) create mode 100644 tests/baselines/reference/arrayFind.js create mode 100644 tests/baselines/reference/arrayFind.symbols create mode 100644 tests/baselines/reference/arrayFind.types create mode 100644 tests/cases/compiler/arrayFind.ts diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index 5c2438d905216..9ea773e3eefc6 100644 --- a/src/lib/es2015.core.d.ts +++ b/src/lib/es2015.core.d.ts @@ -10,6 +10,7 @@ interface Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ + find(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined; find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined; /** @@ -350,6 +351,7 @@ interface ReadonlyArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ + find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray) => value is S, thisArg?: any): S | undefined; find(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): T | undefined; /** diff --git a/tests/baselines/reference/arrayFind.js b/tests/baselines/reference/arrayFind.js new file mode 100644 index 0000000000000..1926c3a8dcc15 --- /dev/null +++ b/tests/baselines/reference/arrayFind.js @@ -0,0 +1,22 @@ +//// [arrayFind.ts] +// test fix for #18112, type guard predicates should narrow returned element +function isNumber(x: any): x is number { + return typeof x === "number"; +} + +const arrayOfStringsNumbersAndBooleans = ["string", false, 0, "strung", 1, true]; +const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(isNumber); + +const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray; +const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber); + + +//// [arrayFind.js] +// test fix for #18112, type guard predicates should narrow returned element +function isNumber(x) { + return typeof x === "number"; +} +var arrayOfStringsNumbersAndBooleans = ["string", false, 0, "strung", 1, true]; +var foundNumber = arrayOfStringsNumbersAndBooleans.find(isNumber); +var readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans; +var readonlyFoundNumber = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber); diff --git a/tests/baselines/reference/arrayFind.symbols b/tests/baselines/reference/arrayFind.symbols new file mode 100644 index 0000000000000..163d5d818ba99 --- /dev/null +++ b/tests/baselines/reference/arrayFind.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/arrayFind.ts === +// test fix for #18112, type guard predicates should narrow returned element +function isNumber(x: any): x is number { +>isNumber : Symbol(isNumber, Decl(arrayFind.ts, 0, 0)) +>x : Symbol(x, Decl(arrayFind.ts, 1, 18)) +>x : Symbol(x, Decl(arrayFind.ts, 1, 18)) + + return typeof x === "number"; +>x : Symbol(x, Decl(arrayFind.ts, 1, 18)) +} + +const arrayOfStringsNumbersAndBooleans = ["string", false, 0, "strung", 1, true]; +>arrayOfStringsNumbersAndBooleans : Symbol(arrayOfStringsNumbersAndBooleans, Decl(arrayFind.ts, 5, 5)) + +const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(isNumber); +>foundNumber : Symbol(foundNumber, Decl(arrayFind.ts, 6, 5)) +>arrayOfStringsNumbersAndBooleans.find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>arrayOfStringsNumbersAndBooleans : Symbol(arrayOfStringsNumbersAndBooleans, Decl(arrayFind.ts, 5, 5)) +>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>isNumber : Symbol(isNumber, Decl(arrayFind.ts, 0, 0)) + +const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray; +>readonlyArrayOfStringsNumbersAndBooleans : Symbol(readonlyArrayOfStringsNumbersAndBooleans, Decl(arrayFind.ts, 8, 5)) +>arrayOfStringsNumbersAndBooleans : Symbol(arrayOfStringsNumbersAndBooleans, Decl(arrayFind.ts, 5, 5)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) + +const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber); +>readonlyFoundNumber : Symbol(readonlyFoundNumber, Decl(arrayFind.ts, 9, 5)) +>readonlyArrayOfStringsNumbersAndBooleans.find : Symbol(ReadonlyArray.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>readonlyArrayOfStringsNumbersAndBooleans : Symbol(readonlyArrayOfStringsNumbersAndBooleans, Decl(arrayFind.ts, 8, 5)) +>find : Symbol(ReadonlyArray.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>isNumber : Symbol(isNumber, Decl(arrayFind.ts, 0, 0)) + diff --git a/tests/baselines/reference/arrayFind.types b/tests/baselines/reference/arrayFind.types new file mode 100644 index 0000000000000..5c0769cb60675 --- /dev/null +++ b/tests/baselines/reference/arrayFind.types @@ -0,0 +1,46 @@ +=== tests/cases/compiler/arrayFind.ts === +// test fix for #18112, type guard predicates should narrow returned element +function isNumber(x: any): x is number { +>isNumber : (x: any) => x is number +>x : any +>x : any + + return typeof x === "number"; +>typeof x === "number" : boolean +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : any +>"number" : "number" +} + +const arrayOfStringsNumbersAndBooleans = ["string", false, 0, "strung", 1, true]; +>arrayOfStringsNumbersAndBooleans : (string | number | boolean)[] +>["string", false, 0, "strung", 1, true] : (string | number | boolean)[] +>"string" : "string" +>false : false +>0 : 0 +>"strung" : "strung" +>1 : 1 +>true : true + +const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(isNumber); +>foundNumber : number +>arrayOfStringsNumbersAndBooleans.find(isNumber) : number +>arrayOfStringsNumbersAndBooleans.find : { (predicate: (this: void, value: string | number | boolean, index: number, obj: (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; } +>arrayOfStringsNumbersAndBooleans : (string | number | boolean)[] +>find : { (predicate: (this: void, value: string | number | boolean, index: number, obj: (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; } +>isNumber : (x: any) => x is number + +const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray; +>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray +>arrayOfStringsNumbersAndBooleans as ReadonlyArray : ReadonlyArray +>arrayOfStringsNumbersAndBooleans : (string | number | boolean)[] +>ReadonlyArray : ReadonlyArray + +const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber); +>readonlyFoundNumber : number +>readonlyArrayOfStringsNumbersAndBooleans.find(isNumber) : number +>readonlyArrayOfStringsNumbersAndBooleans.find : { (predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): string | number | boolean; } +>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray +>find : { (predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): string | number | boolean; } +>isNumber : (x: any) => x is number + diff --git a/tests/cases/compiler/arrayFind.ts b/tests/cases/compiler/arrayFind.ts new file mode 100644 index 0000000000000..90883974766b7 --- /dev/null +++ b/tests/cases/compiler/arrayFind.ts @@ -0,0 +1,12 @@ +// @lib: es2015 + +// test fix for #18112, type guard predicates should narrow returned element +function isNumber(x: any): x is number { + return typeof x === "number"; +} + +const arrayOfStringsNumbersAndBooleans = ["string", false, 0, "strung", 1, true]; +const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(isNumber); + +const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray; +const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber); From 661ecc241ebd2ac6f29f6cd7d37273e4b963be09 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Tue, 10 Oct 2017 07:08:22 +0900 Subject: [PATCH 079/246] Improve Object.{values,entries} static methods (#18875) --- src/lib/es2017.object.d.ts | 4 ++-- .../useObjectValuesAndEntries1.types | 20 +++++++++---------- .../useObjectValuesAndEntries4.types | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lib/es2017.object.d.ts b/src/lib/es2017.object.d.ts index 1d8a52da758a8..4014e8c29278a 100644 --- a/src/lib/es2017.object.d.ts +++ b/src/lib/es2017.object.d.ts @@ -3,7 +3,7 @@ interface ObjectConstructor { * Returns an array of values of the enumerable properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ - values(o: { [s: string]: T }): T[]; + values(o: { [s: string]: T } | { [n: number]: T }): T[]; /** * Returns an array of values of the enumerable properties of an object @@ -15,7 +15,7 @@ interface ObjectConstructor { * Returns an array of key/values of the enumerable properties of an object * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object. */ - entries(o: { [s: string]: T }): [string, T][]; + entries(o: { [s: string]: T } | { [n: number]: T }): [string, T][]; /** * Returns an array of key/values of the enumerable properties of an object diff --git a/tests/baselines/reference/useObjectValuesAndEntries1.types b/tests/baselines/reference/useObjectValuesAndEntries1.types index 1b537ed063d82..6ea45385bbcd9 100644 --- a/tests/baselines/reference/useObjectValuesAndEntries1.types +++ b/tests/baselines/reference/useObjectValuesAndEntries1.types @@ -10,9 +10,9 @@ var o = { a: 1, b: 2 }; for (var x of Object.values(o)) { >x : number >Object.values(o) : number[] ->Object.values : { (o: { [s: string]: T; }): T[]; (o: any): any[]; } +>Object.values : { (o: { [s: string]: T; } | { [n: number]: T; }): T[]; (o: any): any[]; } >Object : ObjectConstructor ->values : { (o: { [s: string]: T; }): T[]; (o: any): any[]; } +>values : { (o: { [s: string]: T; } | { [n: number]: T; }): T[]; (o: any): any[]; } >o : { a: number; b: number; } let y = x; @@ -23,25 +23,25 @@ for (var x of Object.values(o)) { var entries = Object.entries(o); // <-- entries: ['a' | 'b', number][] >entries : [string, number][] >Object.entries(o) : [string, number][] ->Object.entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>Object.entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >Object : ObjectConstructor ->entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >o : { a: number; b: number; } var entries1 = Object.entries(1); // <-- entries: [string, any][] >entries1 : [string, any][] >Object.entries(1) : [string, any][] ->Object.entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>Object.entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >Object : ObjectConstructor ->entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >1 : 1 var entries2 = Object.entries({a: true, b: 2}) // ['a' | 'b', number | boolean][] >entries2 : [string, number | boolean][] >Object.entries({a: true, b: 2}) : [string, number | boolean][] ->Object.entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>Object.entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >Object : ObjectConstructor ->entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >{a: true, b: 2} : { a: true; b: 2; } >a : boolean >true : true @@ -51,8 +51,8 @@ var entries2 = Object.entries({a: true, b: 2}) // ['a' | 'b', number | boolean][ var entries3 = Object.entries({}) // [never, any][] >entries3 : [string, {}][] >Object.entries({}) : [string, {}][] ->Object.entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>Object.entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >Object : ObjectConstructor ->entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >{} : {} diff --git a/tests/baselines/reference/useObjectValuesAndEntries4.types b/tests/baselines/reference/useObjectValuesAndEntries4.types index 85810bccd267f..245803a24d435 100644 --- a/tests/baselines/reference/useObjectValuesAndEntries4.types +++ b/tests/baselines/reference/useObjectValuesAndEntries4.types @@ -10,9 +10,9 @@ var o = { a: 1, b: 2 }; for (var x of Object.values(o)) { >x : number >Object.values(o) : number[] ->Object.values : { (o: { [s: string]: T; }): T[]; (o: any): any[]; } +>Object.values : { (o: { [s: string]: T; } | { [n: number]: T; }): T[]; (o: any): any[]; } >Object : ObjectConstructor ->values : { (o: { [s: string]: T; }): T[]; (o: any): any[]; } +>values : { (o: { [s: string]: T; } | { [n: number]: T; }): T[]; (o: any): any[]; } >o : { a: number; b: number; } let y = x; @@ -23,8 +23,8 @@ for (var x of Object.values(o)) { var entries = Object.entries(o); >entries : [string, number][] >Object.entries(o) : [string, number][] ->Object.entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>Object.entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >Object : ObjectConstructor ->entries : { (o: { [s: string]: T; }): [string, T][]; (o: any): [string, any][]; } +>entries : { (o: { [s: string]: T; } | { [n: number]: T; }): [string, T][]; (o: any): [string, any][]; } >o : { a: number; b: number; } From 6887dbc75028f225d25ed91815de1719e5a1e101 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 9 Oct 2017 15:24:00 -0700 Subject: [PATCH 080/246] Assert if the script info that is attached to closed project is present Adds assertion to investigate #19003 and #18928 --- src/server/editorServices.ts | 3 +++ src/server/project.ts | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2916fb60c5734..40c196009e359 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -832,6 +832,9 @@ namespace ts.server { this.logger.info(`remove project: ${project.getRootFiles().toString()}`); project.close(); + if (Debug.shouldAssert(AssertionLevel.Normal)) { + this.filenameToScriptInfo.forEach(info => Debug.assert(!info.isAttached(project))); + } // Remove the project from pending project updates this.pendingProjectUpdates.delete(project.getProjectName()); diff --git a/src/server/project.ts b/src/server/project.ts index 5132b82a804fd..e8bfd7c1b75a5 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -497,12 +497,7 @@ namespace ts.server { if (this.program) { // if we have a program - release all files that are enlisted in program for (const f of this.program.getSourceFiles()) { - const info = this.projectService.getScriptInfo(f.fileName); - // We might not find the script info in case its not associated with the project any more - // and project graph was not updated (eg delayed update graph in case of files changed/deleted on the disk) - if (info) { - info.detachFromProject(this); - } + this.detachScriptInfo(f.fileName); } } if (!this.program || !this.languageServiceEnabled) { @@ -512,10 +507,13 @@ namespace ts.server { root.detachFromProject(this); } } + this.rootFiles = undefined; this.rootFilesMap = undefined; this.program = undefined; this.builder = undefined; + forEach(this.externalFiles, externalFile => this.detachScriptInfo(externalFile)); + this.externalFiles = undefined; this.resolutionCache.clear(); this.resolutionCache = undefined; this.cachedUnresolvedImportsPerFile = undefined; @@ -532,6 +530,15 @@ namespace ts.server { this.languageService = undefined; } + private detachScriptInfo(uncheckedFilename: string) { + const info = this.projectService.getScriptInfo(uncheckedFilename); + // We might not find the script info in case its not associated with the project any more + // and project graph was not updated (eg delayed update graph in case of files changed/deleted on the disk) + if (info) { + info.detachFromProject(this); + } + } + isClosed() { return this.rootFiles === undefined; } @@ -791,7 +798,7 @@ namespace ts.server { private updateGraphWorker() { const oldProgram = this.program; - + Debug.assert(!this.isClosed(), "Called update graph worker of closed project"); this.writeLog(`Starting updateGraphWorker: Project: ${this.getProjectName()}`); const start = timestamp(); this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution(); From aaa06122b9d7b064d702591be063cea2c7c78e91 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 9 Oct 2017 15:40:52 -0700 Subject: [PATCH 081/246] Fix recursive reference in type parameter default --- src/compiler/checker.ts | 56 ++++++++++++++----- src/compiler/diagnosticMessages.json | 4 ++ tests/baselines/reference/genericDefaults.js | 7 ++- .../reference/genericDefaults.symbols | 6 ++ .../baselines/reference/genericDefaults.types | 6 ++ .../genericDefaultsErrors.errors.txt | 10 +++- .../reference/genericDefaultsErrors.js | 5 +- .../reference/genericDefaultsErrors.symbols | 6 ++ .../reference/genericDefaultsErrors.types | 6 ++ tests/cases/compiler/genericDefaults.ts | 5 +- tests/cases/compiler/genericDefaultsErrors.ts | 5 +- 11 files changed, 96 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d47a77a74401a..4c6973f30485f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -281,6 +281,7 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const resolvingDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const markerSuperType = createType(TypeFlags.TypeParameter); const markerSubType = createType(TypeFlags.TypeParameter); @@ -6055,27 +6056,51 @@ namespace ts { return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type)); } - /** - * Gets the default type for a type parameter. - * - * If the type parameter is the result of an instantiation, this gets the instantiated - * default type of its target. If the type parameter has no default type, `undefined` - * is returned. - * - * This function *does not* perform a circularity check. - */ - function getDefaultFromTypeParameter(typeParameter: TypeParameter): Type | undefined { + function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined { if (!typeParameter.default) { if (typeParameter.target) { - const targetDefault = getDefaultFromTypeParameter(typeParameter.target); + const targetDefault = getResolvedTypeParameterDefault(typeParameter.target); typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; } else { + // To block recursion, set the initial value to the resolvingDefaultType. + typeParameter.default = resolvingDefaultType; const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default); - typeParameter.default = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; + const defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; + if (typeParameter.default === resolvingDefaultType) { + // If we have not been called recursively, set the correct default type. + typeParameter.default = defaultType; + } } } - return typeParameter.default === noConstraintType ? undefined : typeParameter.default; + else if (typeParameter.default === resolvingDefaultType) { + // If we are called recursively for this type parameter, mark the default as circular. + typeParameter.default = circularConstraintType; + } + return typeParameter.default; + } + + /** + * Gets the default type for a type parameter. + * + * If the type parameter is the result of an instantiation, this gets the instantiated + * default type of its target. If the type parameter has no default type or the default is + * circular, `undefined` is returned. + */ + function getDefaultFromTypeParameter(typeParameter: TypeParameter): Type | undefined { + const defaultType = getResolvedTypeParameterDefault(typeParameter); + return defaultType !== noConstraintType && defaultType !== circularConstraintType ? defaultType : undefined; + } + + function hasNonCircularTypeParameterDefault(typeParameter: TypeParameter) { + return getResolvedTypeParameterDefault(typeParameter) !== circularConstraintType; + } + + /** + * Indicates whether the declaration of a typeParameter has a default type. + */ + function hasTypeParameterDefault(typeParameter: TypeParameter): boolean { + return !!(typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default)); } /** @@ -6361,7 +6386,7 @@ namespace ts { let minTypeArgumentCount = 0; if (typeParameters) { for (let i = 0; i < typeParameters.length; i++) { - if (!getDefaultFromTypeParameter(typeParameters[i])) { + if (!hasTypeParameterDefault(typeParameters[i])) { minTypeArgumentCount = i + 1; } } @@ -18478,6 +18503,9 @@ namespace ts { if (!hasNonCircularBaseConstraint(typeParameter)) { error(node.constraint, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(typeParameter)); } + if (!hasNonCircularTypeParameterDefault(typeParameter)) { + error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter)); + } const constraintType = getConstraintOfTypeParameter(typeParameter); const defaultType = getDefaultFromTypeParameter(typeParameter); if (constraintType && defaultType) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 91ad9e52bfd60..3389bc1063e75 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2224,6 +2224,10 @@ "category": "Error", "code": 2715 }, + "Type parameter '{0}' has a circular default.": { + "category": "Error", + "code": 2716 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/genericDefaults.js b/tests/baselines/reference/genericDefaults.js index 06503b89d58ae..be6b76ea43cdb 100644 --- a/tests/baselines/reference/genericDefaults.js +++ b/tests/baselines/reference/genericDefaults.js @@ -487,7 +487,10 @@ const t03c00 = (>x).a; const t03c01 = (>x).a; const t03c02 = (>x).a; const t03c03 = (>x).a; -const t03c04 = (>x).a; +const t03c04 = (>x).a; + +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference> {} //// [genericDefaults.js] // no inference @@ -1024,3 +1027,5 @@ declare const t03c01: [1, 1]; declare const t03c02: [number, number]; declare const t03c03: [1, 1]; declare const t03c04: [number, 1]; +interface SelfReference> { +} diff --git a/tests/baselines/reference/genericDefaults.symbols b/tests/baselines/reference/genericDefaults.symbols index 6c9e97b265e0a..755a34c7a63be 100644 --- a/tests/baselines/reference/genericDefaults.symbols +++ b/tests/baselines/reference/genericDefaults.symbols @@ -2291,3 +2291,9 @@ const t03c04 = (>x).a; >x : Symbol(x, Decl(genericDefaults.ts, 13, 13)) >a : Symbol(a, Decl(genericDefaults.ts, 483, 47)) +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference> {} +>SelfReference : Symbol(SelfReference, Decl(genericDefaults.ts, 488, 37)) +>T : Symbol(T, Decl(genericDefaults.ts, 491, 24)) +>SelfReference : Symbol(SelfReference, Decl(genericDefaults.ts, 488, 37)) + diff --git a/tests/baselines/reference/genericDefaults.types b/tests/baselines/reference/genericDefaults.types index 739588badb9c1..0013daefd8917 100644 --- a/tests/baselines/reference/genericDefaults.types +++ b/tests/baselines/reference/genericDefaults.types @@ -2643,3 +2643,9 @@ const t03c04 = (>x).a; >x : any >a : [number, 1] +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference> {} +>SelfReference : SelfReference +>T : T +>SelfReference : SelfReference + diff --git a/tests/baselines/reference/genericDefaultsErrors.errors.txt b/tests/baselines/reference/genericDefaultsErrors.errors.txt index 6200046c49fc9..762bb92535b5c 100644 --- a/tests/baselines/reference/genericDefaultsErrors.errors.txt +++ b/tests/baselines/reference/genericDefaultsErrors.errors.txt @@ -21,9 +21,10 @@ tests/cases/compiler/genericDefaultsErrors.ts(33,15): error TS2707: Generic type tests/cases/compiler/genericDefaultsErrors.ts(36,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. tests/cases/compiler/genericDefaultsErrors.ts(38,20): error TS2304: Cannot find name 'T'. tests/cases/compiler/genericDefaultsErrors.ts(38,20): error TS4033: Property 'x' of exported interface has or is using private name 'T'. +tests/cases/compiler/genericDefaultsErrors.ts(42,29): error TS2715: Type parameter 'T' has a circular default. -==== tests/cases/compiler/genericDefaultsErrors.ts (21 errors) ==== +==== tests/cases/compiler/genericDefaultsErrors.ts (22 errors) ==== declare const x: any; declare function f03(): void; // error @@ -106,4 +107,9 @@ tests/cases/compiler/genericDefaultsErrors.ts(38,20): error TS4033: Property 'x' !!! error TS2304: Cannot find name 'T'. ~ !!! error TS4033: Property 'x' of exported interface has or is using private name 'T'. - interface i10 {} \ No newline at end of file + interface i10 {} + + // https://github.com/Microsoft/TypeScript/issues/16221 + interface SelfReference {} + ~~~~~~~~~~~~~ +!!! error TS2715: Type parameter 'T' has a circular default. \ No newline at end of file diff --git a/tests/baselines/reference/genericDefaultsErrors.js b/tests/baselines/reference/genericDefaultsErrors.js index c737644e99959..19201172b2f40 100644 --- a/tests/baselines/reference/genericDefaultsErrors.js +++ b/tests/baselines/reference/genericDefaultsErrors.js @@ -37,7 +37,10 @@ type i09t03 = i09<1, 2, 3>; // ok type i09t04 = i09<1, 2, 3, 4>; // error interface i10 { x: T; } // error -interface i10 {} +interface i10 {} + +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference {} //// [genericDefaultsErrors.js] f11(); // ok diff --git a/tests/baselines/reference/genericDefaultsErrors.symbols b/tests/baselines/reference/genericDefaultsErrors.symbols index 495b56ea25a8d..e6e5cb860622d 100644 --- a/tests/baselines/reference/genericDefaultsErrors.symbols +++ b/tests/baselines/reference/genericDefaultsErrors.symbols @@ -136,3 +136,9 @@ interface i10 {} >i10 : Symbol(i10, Decl(genericDefaultsErrors.ts, 35, 30), Decl(genericDefaultsErrors.ts, 37, 23)) >T : Symbol(T, Decl(genericDefaultsErrors.ts, 38, 14)) +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference {} +>SelfReference : Symbol(SelfReference, Decl(genericDefaultsErrors.ts, 38, 28)) +>T : Symbol(T, Decl(genericDefaultsErrors.ts, 41, 24)) +>SelfReference : Symbol(SelfReference, Decl(genericDefaultsErrors.ts, 38, 28)) + diff --git a/tests/baselines/reference/genericDefaultsErrors.types b/tests/baselines/reference/genericDefaultsErrors.types index 46bae67bc258a..87e9af0bb072c 100644 --- a/tests/baselines/reference/genericDefaultsErrors.types +++ b/tests/baselines/reference/genericDefaultsErrors.types @@ -145,3 +145,9 @@ interface i10 {} >i10 : i10 >T : T +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference {} +>SelfReference : SelfReference +>T : T +>SelfReference : SelfReference + diff --git a/tests/cases/compiler/genericDefaults.ts b/tests/cases/compiler/genericDefaults.ts index 624b44c0829ee..e7b9c95edebea 100644 --- a/tests/cases/compiler/genericDefaults.ts +++ b/tests/cases/compiler/genericDefaults.ts @@ -487,4 +487,7 @@ const t03c00 = (>x).a; const t03c01 = (>x).a; const t03c02 = (>x).a; const t03c03 = (>x).a; -const t03c04 = (>x).a; \ No newline at end of file +const t03c04 = (>x).a; + +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference> {} \ No newline at end of file diff --git a/tests/cases/compiler/genericDefaultsErrors.ts b/tests/cases/compiler/genericDefaultsErrors.ts index 4ea42beb3da1a..9cdba888327c4 100644 --- a/tests/cases/compiler/genericDefaultsErrors.ts +++ b/tests/cases/compiler/genericDefaultsErrors.ts @@ -38,4 +38,7 @@ type i09t03 = i09<1, 2, 3>; // ok type i09t04 = i09<1, 2, 3, 4>; // error interface i10 { x: T; } // error -interface i10 {} \ No newline at end of file +interface i10 {} + +// https://github.com/Microsoft/TypeScript/issues/16221 +interface SelfReference {} \ No newline at end of file From b9592d4186ac04ba9690ae6d2f86697ddcf820a9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 9 Oct 2017 15:59:27 -0700 Subject: [PATCH 082/246] Use the parent most node_modules directory for module resolution failed lookup locations --- src/compiler/resolutionCache.ts | 14 +++---- .../unittests/tsserverProjectSystem.ts | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index aecc698989134..25545c0efbc80 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -323,19 +323,17 @@ namespace ts { let dir = getDirectoryPath(getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())); let dirPath = getDirectoryPath(failedLookupLocationPath); + // If directory path contains node module, get the most parent node_modules directory for watching + while (dirPath.indexOf("/node_modules/") !== -1) { + dir = getDirectoryPath(dir); + dirPath = getDirectoryPath(dirPath); + } + // If the directory is node_modules use it to watch if (isNodeModulesDirectory(dirPath)) { return { dir, dirPath }; } - // If directory path contains node module, get the node_modules directory for watching - if (dirPath.indexOf("/node_modules/") !== -1) { - while (!isNodeModulesDirectory(dirPath)) { - dir = getDirectoryPath(dir); - dirPath = getDirectoryPath(dirPath); - } - return { dir, dirPath }; - } // Use some ancestor of the root directory if (rootPath !== undefined) { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 06e2beeaaa6cf..2f875456e06e5 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2399,6 +2399,43 @@ namespace ts.projectSystem { checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); }); + + it("Failed lookup locations are uses parent most node_modules directory", () => { + const file1: FileOrFolder = { + path: "/a/b/src/file1.ts", + content: 'import { classc } from "module1"' + }; + const module1: FileOrFolder = { + path: "/a/b/node_modules/module1/index.d.ts", + content: `import { class2 } from "module2"; + export classc { method2a(): class2; }` + }; + const module2: FileOrFolder = { + path: "/a/b/node_modules/module2/index.d.ts", + content: "export class2 { method2() { return 10; } }" + }; + const module3: FileOrFolder = { + path: "/a/b/node_modules/module/node_modules/module3/index.d.ts", + content: "export class3 { method2() { return 10; } }" + }; + const configFile: FileOrFolder = { + path: "/a/b/src/tsconfig.json", + content: JSON.stringify({ files: [file1.path] }) + }; + const files = [file1, module1, module2, module3, configFile, libFile]; + const host = createServerHost(files); + const projectService = createProjectService(host); + projectService.openClientFile(file1.path); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const project = projectService.configuredProjects.get(configFile.path); + assert.isDefined(project); + checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); + checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]); + checkWatchedDirectories(host, [], /*recursive*/ false); + const watchedRecursiveDirectories = getTypeRootsFromLocation("/a/b/src"); + watchedRecursiveDirectories.push("/a/b/src", "/a/b/node_modules"); + checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); + }); }); describe("Proper errors", () => { From 17a1cd069dc4d1f45f09f57186f94e45505b5ed6 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 9 Oct 2017 16:55:20 -0700 Subject: [PATCH 083/246] Add deprecation warning to getSymbolDisplayBuilder (#18953) * Add deprecation warning to getSymbolDisplayBuilder * Accept API baselines --- src/compiler/types.ts | 4 ++++ tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++++ tests/baselines/reference/api/typescript.d.ts | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 13a23b77a0a29..67b8606df5e9e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2653,6 +2653,10 @@ namespace ts { signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + /** + * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead + * This will be removed in a future version. + */ getSymbolDisplayBuilder(): SymbolDisplayBuilder; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ce926dfc04093..6da4262e0b780 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1731,6 +1731,10 @@ declare namespace ts { signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + /** + * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead + * This will be removed in a future version. + */ getSymbolDisplayBuilder(): SymbolDisplayBuilder; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index b8fd072c85234..0c74f74c7413c 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1731,6 +1731,10 @@ declare namespace ts { signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; + /** + * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead + * This will be removed in a future version. + */ getSymbolDisplayBuilder(): SymbolDisplayBuilder; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; From d23e5f1ee2fbe67db4ed0a5ac6dc856dfc7ce9c8 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Tue, 10 Oct 2017 09:11:31 +0900 Subject: [PATCH 084/246] Fix Array.{reduce,reduceRight} methods (#18987) --- src/lib/es5.d.ts | 66 ++++++++++++------- .../anyInferenceAnonymousFunctions.symbols | 12 ++-- .../anyInferenceAnonymousFunctions.types | 12 ++-- ...plicateOverloadInTypeAugmentation1.symbols | 8 +-- ...duplicateOverloadInTypeAugmentation1.types | 8 +-- ...ericContextualTypingSpecialization.symbols | 4 +- ...enericContextualTypingSpecialization.types | 4 +- .../baselines/reference/genericReduce.symbols | 12 ++-- tests/baselines/reference/genericReduce.types | 12 ++-- ...ferFromGenericFunctionReturnTypes1.symbols | 4 +- ...inferFromGenericFunctionReturnTypes1.types | 4 +- ...ferFromGenericFunctionReturnTypes2.symbols | 4 +- ...inferFromGenericFunctionReturnTypes2.types | 4 +- .../baselines/reference/parserharness.symbols | 12 ++-- tests/baselines/reference/parserharness.types | 12 ++-- .../reference/recursiveTypeRelations.symbols | 4 +- .../reference/recursiveTypeRelations.types | 4 +- .../reference/restInvalidArgumentType.types | 2 +- .../returnTypeParameterWithModules.symbols | 4 +- .../returnTypeParameterWithModules.types | 4 +- .../reference/spreadInvalidArgumentType.types | 4 +- .../unknownSymbolOffContextualType1.symbols | 4 +- .../unknownSymbolOffContextualType1.types | 4 +- 23 files changed, 115 insertions(+), 93 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index e08534d8ba94f..fd2ae5b3fdfa7 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1050,7 +1050,8 @@ interface ReadonlyArray { * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T, initialValue?: T): T; + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T): T; + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T, initialValue: T): T; /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. @@ -1062,7 +1063,8 @@ interface ReadonlyArray { * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T, initialValue?: T): T; + reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T): T; + reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray) => T, initialValue: T): T; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. @@ -1200,7 +1202,8 @@ interface Array { * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; + reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. @@ -1212,7 +1215,8 @@ interface Array { * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; + reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; + reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. @@ -1647,7 +1651,8 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -1671,7 +1676,8 @@ interface Int8Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -1914,7 +1920,8 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -1938,7 +1945,8 @@ interface Uint8Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2181,7 +2189,8 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2205,7 +2214,8 @@ interface Uint8ClampedArray { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2446,7 +2456,8 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2470,7 +2481,8 @@ interface Int16Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2714,7 +2726,8 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -2738,7 +2751,8 @@ interface Uint16Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -2981,7 +2995,8 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3005,7 +3020,8 @@ interface Int32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3247,7 +3263,8 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3271,7 +3288,8 @@ interface Uint32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3514,7 +3532,8 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3538,7 +3557,8 @@ interface Float32Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. @@ -3782,7 +3802,8 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ - reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number): number; + reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array. The return value of @@ -3806,7 +3827,8 @@ interface Float64Array { * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ - reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number): number; + reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue: number): number; /** * Calls the specified callback function for all the elements in an array, in descending order. diff --git a/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols b/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols index c1b5df88fb0b2..4aad165f40aa8 100644 --- a/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols +++ b/tests/baselines/reference/anyInferenceAnonymousFunctions.symbols @@ -3,9 +3,9 @@ var paired: any[]; >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) paired.reduce(function (a1, a2) { ->paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >a1 : Symbol(a1, Decl(anyInferenceAnonymousFunctions.ts, 2, 24)) >a2 : Symbol(a2, Decl(anyInferenceAnonymousFunctions.ts, 2, 27)) @@ -15,9 +15,9 @@ paired.reduce(function (a1, a2) { } , []); paired.reduce((b1, b2) => { ->paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b1 : Symbol(b1, Decl(anyInferenceAnonymousFunctions.ts, 8, 15)) >b2 : Symbol(b2, Decl(anyInferenceAnonymousFunctions.ts, 8, 18)) @@ -27,9 +27,9 @@ paired.reduce((b1, b2) => { } , []); paired.reduce((b3, b4) => b3.concat({}), []); ->paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>paired.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b3 : Symbol(b3, Decl(anyInferenceAnonymousFunctions.ts, 13, 15)) >b4 : Symbol(b4, Decl(anyInferenceAnonymousFunctions.ts, 13, 18)) >b3 : Symbol(b3, Decl(anyInferenceAnonymousFunctions.ts, 13, 15)) diff --git a/tests/baselines/reference/anyInferenceAnonymousFunctions.types b/tests/baselines/reference/anyInferenceAnonymousFunctions.types index 8dc7fdcb90f1d..d5f693b5453b4 100644 --- a/tests/baselines/reference/anyInferenceAnonymousFunctions.types +++ b/tests/baselines/reference/anyInferenceAnonymousFunctions.types @@ -4,9 +4,9 @@ var paired: any[]; paired.reduce(function (a1, a2) { >paired.reduce(function (a1, a2) { return a1.concat({});} , []) : any ->paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >paired : any[] ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >function (a1, a2) { return a1.concat({});} : (a1: any, a2: any) => any >a1 : any >a2 : any @@ -23,9 +23,9 @@ paired.reduce(function (a1, a2) { paired.reduce((b1, b2) => { >paired.reduce((b1, b2) => { return b1.concat({});} , []) : any ->paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >paired : any[] ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >(b1, b2) => { return b1.concat({});} : (b1: any, b2: any) => any >b1 : any >b2 : any @@ -42,9 +42,9 @@ paired.reduce((b1, b2) => { paired.reduce((b3, b4) => b3.concat({}), []); >paired.reduce((b3, b4) => b3.concat({}), []) : any ->paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>paired.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >paired : any[] ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >(b3, b4) => b3.concat({}) : (b3: any, b4: any) => any >b3 : any >b4 : any diff --git a/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.symbols b/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.symbols index 02589e011c4d6..31efb739e4cfe 100644 --- a/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.symbols +++ b/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.symbols @@ -4,7 +4,7 @@ interface Array { >T : Symbol(T, Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 16)) reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) >callbackfn : Symbol(callbackfn, Decl(duplicateOverloadInTypeAugmentation1.ts, 1, 11)) >previousValue : Symbol(previousValue, Decl(duplicateOverloadInTypeAugmentation1.ts, 1, 24)) >T : Symbol(T, Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 16)) @@ -21,7 +21,7 @@ interface Array { >T : Symbol(T, Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 16)) reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) >U : Symbol(U, Decl(duplicateOverloadInTypeAugmentation1.ts, 3, 11)) >callbackfn : Symbol(callbackfn, Decl(duplicateOverloadInTypeAugmentation1.ts, 3, 14)) >previousValue : Symbol(previousValue, Decl(duplicateOverloadInTypeAugmentation1.ts, 3, 27)) @@ -44,9 +44,9 @@ var a: Array; var r5 = a.reduce((x, y) => x + y); >r5 : Symbol(r5, Decl(duplicateOverloadInTypeAugmentation1.ts, 7, 3)) ->a.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) +>a.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) >a : Symbol(a, Decl(duplicateOverloadInTypeAugmentation1.ts, 6, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(duplicateOverloadInTypeAugmentation1.ts, 0, 20), Decl(duplicateOverloadInTypeAugmentation1.ts, 2, 29)) >x : Symbol(x, Decl(duplicateOverloadInTypeAugmentation1.ts, 7, 19)) >y : Symbol(y, Decl(duplicateOverloadInTypeAugmentation1.ts, 7, 21)) >x : Symbol(x, Decl(duplicateOverloadInTypeAugmentation1.ts, 7, 19)) diff --git a/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.types b/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.types index bc7214eb6b941..ea07ece4314ec 100644 --- a/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.types +++ b/tests/baselines/reference/duplicateOverloadInTypeAugmentation1.types @@ -4,7 +4,7 @@ interface Array { >T : T reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, ->reduce : { (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >callbackfn : (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T >previousValue : T >T : T @@ -21,7 +21,7 @@ interface Array { >T : T reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, ->reduce : { (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; (callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >U : U >callbackfn : (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U >previousValue : U @@ -45,9 +45,9 @@ var a: Array; var r5 = a.reduce((x, y) => x + y); >r5 : string >a.reduce((x, y) => x + y) : string ->a.reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } +>a.reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } >a : string[] ->reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } >(x, y) => x + y : (x: string, y: string) => string >x : string >y : string diff --git a/tests/baselines/reference/genericContextualTypingSpecialization.symbols b/tests/baselines/reference/genericContextualTypingSpecialization.symbols index b244ab496be44..0dcc8cb5899c6 100644 --- a/tests/baselines/reference/genericContextualTypingSpecialization.symbols +++ b/tests/baselines/reference/genericContextualTypingSpecialization.symbols @@ -3,9 +3,9 @@ var b: number[]; >b : Symbol(b, Decl(genericContextualTypingSpecialization.ts, 0, 3)) b.reduce((c, d) => c + d, 0); // should not error on '+' ->b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(genericContextualTypingSpecialization.ts, 0, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >c : Symbol(c, Decl(genericContextualTypingSpecialization.ts, 1, 18)) >d : Symbol(d, Decl(genericContextualTypingSpecialization.ts, 1, 20)) >c : Symbol(c, Decl(genericContextualTypingSpecialization.ts, 1, 18)) diff --git a/tests/baselines/reference/genericContextualTypingSpecialization.types b/tests/baselines/reference/genericContextualTypingSpecialization.types index 8225502034731..d7d6101050799 100644 --- a/tests/baselines/reference/genericContextualTypingSpecialization.types +++ b/tests/baselines/reference/genericContextualTypingSpecialization.types @@ -4,9 +4,9 @@ var b: number[]; b.reduce((c, d) => c + d, 0); // should not error on '+' >b.reduce((c, d) => c + d, 0) : number ->b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >b : number[] ->reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >(c, d) => c + d : (c: number, d: number) => number >c : number >d : number diff --git a/tests/baselines/reference/genericReduce.symbols b/tests/baselines/reference/genericReduce.symbols index f220972a35086..a939c5cf92d60 100644 --- a/tests/baselines/reference/genericReduce.symbols +++ b/tests/baselines/reference/genericReduce.symbols @@ -14,9 +14,9 @@ var b = a.map(s => s.length); var n1 = b.reduce((x, y) => x + y); >n1 : Symbol(n1, Decl(genericReduce.ts, 2, 3)) ->b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(genericReduce.ts, 1, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(genericReduce.ts, 2, 19)) >y : Symbol(y, Decl(genericReduce.ts, 2, 21)) >x : Symbol(x, Decl(genericReduce.ts, 2, 19)) @@ -24,9 +24,9 @@ var n1 = b.reduce((x, y) => x + y); var n2 = b.reduceRight((x, y) => x + y); >n2 : Symbol(n2, Decl(genericReduce.ts, 3, 3)) ->b.reduceRight : Symbol(Array.reduceRight, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>b.reduceRight : Symbol(Array.reduceRight, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(genericReduce.ts, 1, 3)) ->reduceRight : Symbol(Array.reduceRight, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduceRight : Symbol(Array.reduceRight, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(genericReduce.ts, 3, 24)) >y : Symbol(y, Decl(genericReduce.ts, 3, 26)) >x : Symbol(x, Decl(genericReduce.ts, 3, 24)) @@ -50,9 +50,9 @@ n2.toExponential(2); // should not error if 'n2' is correctly number. var n3 = b.reduce( (x, y) => x + y, ""); // Initial value is of type string >n3 : Symbol(n3, Decl(genericReduce.ts, 10, 3)) ->b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>b.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(genericReduce.ts, 1, 3)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(genericReduce.ts, 10, 28)) >y : Symbol(y, Decl(genericReduce.ts, 10, 30)) >x : Symbol(x, Decl(genericReduce.ts, 10, 28)) diff --git a/tests/baselines/reference/genericReduce.types b/tests/baselines/reference/genericReduce.types index 628398f86fdbf..65a069426a7d5 100644 --- a/tests/baselines/reference/genericReduce.types +++ b/tests/baselines/reference/genericReduce.types @@ -22,9 +22,9 @@ var b = a.map(s => s.length); var n1 = b.reduce((x, y) => x + y); >n1 : number >b.reduce((x, y) => x + y) : number ->b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >b : number[] ->reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >(x, y) => x + y : (x: number, y: number) => number >x : number >y : number @@ -35,9 +35,9 @@ var n1 = b.reduce((x, y) => x + y); var n2 = b.reduceRight((x, y) => x + y); >n2 : number >b.reduceRight((x, y) => x + y) : number ->b.reduceRight : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>b.reduceRight : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >b : number[] ->reduceRight : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>reduceRight : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >(x, y) => x + y : (x: number, y: number) => number >x : number >y : number @@ -76,9 +76,9 @@ n2.toExponential(2); // should not error if 'n2' is correctly number. var n3 = b.reduce( (x, y) => x + y, ""); // Initial value is of type string >n3 : string >b.reduce( (x, y) => x + y, "") : string ->b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>b.reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >b : number[] ->reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >(x, y) => x + y : (x: string, y: number) => string >x : string >y : number diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.symbols index e18c80afcde20..3060f44009b5f 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.symbols +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.symbols @@ -124,9 +124,9 @@ function compose(...fns: ((x: T) => T)[]): (x: T) => T { return (x: T) => fns.reduce((prev, fn) => fn(prev), x); >x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes1.ts, 27, 10)) >T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes1.ts, 26, 17)) ->fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes1.ts, 26, 20)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes1.ts, 27, 31)) >fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes1.ts, 27, 36)) >fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes1.ts, 27, 36)) diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.types index dfbe6c2f2b6a5..9484b3aaa190e 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.types +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes1.types @@ -131,9 +131,9 @@ function compose(...fns: ((x: T) => T)[]): (x: T) => T { >x : T >T : T >fns.reduce((prev, fn) => fn(prev), x) : T ->fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T): (x: T) => T; (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } >fns : ((x: T) => T)[] ->reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T): (x: T) => T; (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } >(prev, fn) => fn(prev) : (prev: T, fn: (x: T) => T) => T >prev : T >fn : (x: T) => T diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols index 7e4fe043b93e5..f71896822736f 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.symbols @@ -292,9 +292,9 @@ function compose(...fns: ((x: T) => T)[]): (x: T) => T { return (x: T) => fns.reduce((prev, fn) => fn(prev), x); >x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 10)) >T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 17)) ->fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>fns.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >fns : Symbol(fns, Decl(inferFromGenericFunctionReturnTypes2.ts, 48, 20)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prev : Symbol(prev, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 31)) >fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36)) >fn : Symbol(fn, Decl(inferFromGenericFunctionReturnTypes2.ts, 49, 36)) diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types index cf7752e237eff..a36b7ed35be7b 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes2.types @@ -358,9 +358,9 @@ function compose(...fns: ((x: T) => T)[]): (x: T) => T { >x : T >T : T >fns.reduce((prev, fn) => fn(prev), x) : T ->fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>fns.reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T): (x: T) => T; (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } >fns : ((x: T) => T)[] ->reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue?: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T): (x: T) => T; (callbackfn: (previousValue: (x: T) => T, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => (x: T) => T, initialValue: (x: T) => T): (x: T) => T; (callbackfn: (previousValue: U, currentValue: (x: T) => T, currentIndex: number, array: ((x: T) => T)[]) => U, initialValue: U): U; } >(prev, fn) => fn(prev) : (prev: T, fn: (x: T) => T) => T >prev : T >fn : (x: T) => T diff --git a/tests/baselines/reference/parserharness.symbols b/tests/baselines/reference/parserharness.symbols index 94ae5c8790125..8382d6ab41ab2 100644 --- a/tests/baselines/reference/parserharness.symbols +++ b/tests/baselines/reference/parserharness.symbols @@ -4692,7 +4692,7 @@ module Harness { var minDistFromStart = entries.map(x => x.editRange.minChar).reduce((prev, current) => Math.min(prev, current)); >minDistFromStart : Symbol(minDistFromStart, Decl(parserharness.ts, 1595, 15)) ->entries.map(x => x.editRange.minChar).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>entries.map(x => x.editRange.minChar).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >entries.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >entries : Symbol(entries, Decl(parserharness.ts, 1593, 15)) >map : Symbol(Array.map, Decl(lib.d.ts, --, --)) @@ -4700,7 +4700,7 @@ module Harness { >x.editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) >x : Symbol(x, Decl(parserharness.ts, 1595, 47)) >editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prev : Symbol(prev, Decl(parserharness.ts, 1595, 81)) >current : Symbol(current, Decl(parserharness.ts, 1595, 86)) >Math.min : Symbol(Math.min, Decl(lib.d.ts, --, --)) @@ -4711,7 +4711,7 @@ module Harness { var minDistFromEnd = entries.map(x => x.length - x.editRange.limChar).reduce((prev, current) => Math.min(prev, current)); >minDistFromEnd : Symbol(minDistFromEnd, Decl(parserharness.ts, 1596, 15)) ->entries.map(x => x.length - x.editRange.limChar).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>entries.map(x => x.length - x.editRange.limChar).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >entries.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >entries : Symbol(entries, Decl(parserharness.ts, 1593, 15)) >map : Symbol(Array.map, Decl(lib.d.ts, --, --)) @@ -4722,7 +4722,7 @@ module Harness { >x.editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) >x : Symbol(x, Decl(parserharness.ts, 1596, 45)) >editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prev : Symbol(prev, Decl(parserharness.ts, 1596, 90)) >current : Symbol(current, Decl(parserharness.ts, 1596, 95)) >Math.min : Symbol(Math.min, Decl(lib.d.ts, --, --)) @@ -4733,7 +4733,7 @@ module Harness { var aggDelta = entries.map(x => x.editRange.delta).reduce((prev, current) => prev + current); >aggDelta : Symbol(aggDelta, Decl(parserharness.ts, 1597, 15)) ->entries.map(x => x.editRange.delta).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>entries.map(x => x.editRange.delta).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >entries.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) >entries : Symbol(entries, Decl(parserharness.ts, 1593, 15)) >map : Symbol(Array.map, Decl(lib.d.ts, --, --)) @@ -4741,7 +4741,7 @@ module Harness { >x.editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) >x : Symbol(x, Decl(parserharness.ts, 1597, 39)) >editRange : Symbol(editRange, Decl(parserharness.ts, 1547, 44)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prev : Symbol(prev, Decl(parserharness.ts, 1597, 71)) >current : Symbol(current, Decl(parserharness.ts, 1597, 76)) >prev : Symbol(prev, Decl(parserharness.ts, 1597, 71)) diff --git a/tests/baselines/reference/parserharness.types b/tests/baselines/reference/parserharness.types index 2fd260f5d2b01..6ea78e22f2fa1 100644 --- a/tests/baselines/reference/parserharness.types +++ b/tests/baselines/reference/parserharness.types @@ -6604,7 +6604,7 @@ module Harness { var minDistFromStart = entries.map(x => x.editRange.minChar).reduce((prev, current) => Math.min(prev, current)); >minDistFromStart : any >entries.map(x => x.editRange.minChar).reduce((prev, current) => Math.min(prev, current)) : any ->entries.map(x => x.editRange.minChar).reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>entries.map(x => x.editRange.minChar).reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >entries.map(x => x.editRange.minChar) : any[] >entries.map : (callbackfn: (value: { length: number; editRange: any; }, index: number, array: { length: number; editRange: any; }[]) => U, thisArg?: any) => U[] >entries : { length: number; editRange: any; }[] @@ -6616,7 +6616,7 @@ module Harness { >x : { length: number; editRange: any; } >editRange : any >minChar : any ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >(prev, current) => Math.min(prev, current) : (prev: any, current: any) => number >prev : any >current : any @@ -6630,7 +6630,7 @@ module Harness { var minDistFromEnd = entries.map(x => x.length - x.editRange.limChar).reduce((prev, current) => Math.min(prev, current)); >minDistFromEnd : number >entries.map(x => x.length - x.editRange.limChar).reduce((prev, current) => Math.min(prev, current)) : number ->entries.map(x => x.length - x.editRange.limChar).reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>entries.map(x => x.length - x.editRange.limChar).reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >entries.map(x => x.length - x.editRange.limChar) : number[] >entries.map : (callbackfn: (value: { length: number; editRange: any; }, index: number, array: { length: number; editRange: any; }[]) => U, thisArg?: any) => U[] >entries : { length: number; editRange: any; }[] @@ -6646,7 +6646,7 @@ module Harness { >x : { length: number; editRange: any; } >editRange : any >limChar : any ->reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue?: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; } >(prev, current) => Math.min(prev, current) : (prev: number, current: number) => number >prev : number >current : number @@ -6660,7 +6660,7 @@ module Harness { var aggDelta = entries.map(x => x.editRange.delta).reduce((prev, current) => prev + current); >aggDelta : any >entries.map(x => x.editRange.delta).reduce((prev, current) => prev + current) : any ->entries.map(x => x.editRange.delta).reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>entries.map(x => x.editRange.delta).reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >entries.map(x => x.editRange.delta) : any[] >entries.map : (callbackfn: (value: { length: number; editRange: any; }, index: number, array: { length: number; editRange: any; }[]) => U, thisArg?: any) => U[] >entries : { length: number; editRange: any; }[] @@ -6672,7 +6672,7 @@ module Harness { >x : { length: number; editRange: any; } >editRange : any >delta : any ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >(prev, current) => prev + current : (prev: any, current: any) => any >prev : any >current : any diff --git a/tests/baselines/reference/recursiveTypeRelations.symbols b/tests/baselines/reference/recursiveTypeRelations.symbols index 9f656a789edb3..2c940df248731 100644 --- a/tests/baselines/reference/recursiveTypeRelations.symbols +++ b/tests/baselines/reference/recursiveTypeRelations.symbols @@ -89,12 +89,12 @@ export function css(styles: S, ...classNam >arg : Symbol(arg, Decl(recursiveTypeRelations.ts, 18, 30)) return Object.keys(arg).reduce((obj: ClassNameObject, key: keyof S) => { ->Object.keys(arg).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Object.keys(arg).reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.d.ts, --, --)) >Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >keys : Symbol(ObjectConstructor.keys, Decl(lib.d.ts, --, --)) >arg : Symbol(arg, Decl(recursiveTypeRelations.ts, 18, 30)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >obj : Symbol(obj, Decl(recursiveTypeRelations.ts, 26, 55)) >key : Symbol(key, Decl(recursiveTypeRelations.ts, 26, 76)) >S : Symbol(S, Decl(recursiveTypeRelations.ts, 17, 20)) diff --git a/tests/baselines/reference/recursiveTypeRelations.types b/tests/baselines/reference/recursiveTypeRelations.types index 6def28d446150..110ff8175c4d2 100644 --- a/tests/baselines/reference/recursiveTypeRelations.types +++ b/tests/baselines/reference/recursiveTypeRelations.types @@ -102,13 +102,13 @@ export function css(styles: S, ...classNam return Object.keys(arg).reduce((obj: ClassNameObject, key: keyof S) => { >Object.keys(arg).reduce((obj: ClassNameObject, key: keyof S) => { const exportedClassName = styles[key]; obj[exportedClassName] = (arg as ClassNameMap)[key]; return obj; }, {}) : any ->Object.keys(arg).reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } +>Object.keys(arg).reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } >Object.keys(arg) : string[] >Object.keys : (o: {}) => string[] >Object : ObjectConstructor >keys : (o: {}) => string[] >arg : keyof S | (object & { [K in keyof S]?: boolean; }) ->reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue?: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; (callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; } >ClassNameObject : No type information available! >(obj: ClassNameObject, key: keyof S) => { const exportedClassName = styles[key]; obj[exportedClassName] = (arg as ClassNameMap)[key]; return obj; } : (obj: any, key: keyof S) => any >obj : any diff --git a/tests/baselines/reference/restInvalidArgumentType.types b/tests/baselines/reference/restInvalidArgumentType.types index 28162bcc7cc08..39495008877a7 100644 --- a/tests/baselines/reference/restInvalidArgumentType.types +++ b/tests/baselines/reference/restInvalidArgumentType.types @@ -87,7 +87,7 @@ function f(p1: T, p2: T[]) { >p1 : T var {...r2} = p2; // OK ->r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>r2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] var {...r3} = t; // Error, generic type paramter diff --git a/tests/baselines/reference/returnTypeParameterWithModules.symbols b/tests/baselines/reference/returnTypeParameterWithModules.symbols index 7f8fab382a31d..eb56940b60405 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.symbols +++ b/tests/baselines/reference/returnTypeParameterWithModules.symbols @@ -13,11 +13,11 @@ module M1 { return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); >Array.prototype.reduce.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) ->Array.prototype.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Array.prototype.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array.prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) >ar : Symbol(ar, Decl(returnTypeParameterWithModules.ts, 1, 30)) >e : Symbol(e, Decl(returnTypeParameterWithModules.ts, 1, 36)) diff --git a/tests/baselines/reference/returnTypeParameterWithModules.types b/tests/baselines/reference/returnTypeParameterWithModules.types index 584c962a170e6..3aec0f14fcf88 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.types +++ b/tests/baselines/reference/returnTypeParameterWithModules.types @@ -14,11 +14,11 @@ module M1 { return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); >Array.prototype.reduce.apply(ar, e ? [f, e] : [f]) : any >Array.prototype.reduce.apply : (this: Function, thisArg: any, argArray?: any) => any ->Array.prototype.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>Array.prototype.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >Array.prototype : any[] >Array : ArrayConstructor >prototype : any[] ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >apply : (this: Function, thisArg: any, argArray?: any) => any >ar : any >e ? [f, e] : [f] : any[] diff --git a/tests/baselines/reference/spreadInvalidArgumentType.types b/tests/baselines/reference/spreadInvalidArgumentType.types index 1eebc00850fe4..244d851589331 100644 --- a/tests/baselines/reference/spreadInvalidArgumentType.types +++ b/tests/baselines/reference/spreadInvalidArgumentType.types @@ -89,8 +89,8 @@ function f(p1: T, p2: T[]) { >p1 : T var o2 = { ...p2 }; // OK ->o2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } ->{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>o2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] var o3 = { ...t }; // Error, generic type paramter diff --git a/tests/baselines/reference/unknownSymbolOffContextualType1.symbols b/tests/baselines/reference/unknownSymbolOffContextualType1.symbols index 1e19afeb6a073..3acf34ec9bf5e 100644 --- a/tests/baselines/reference/unknownSymbolOffContextualType1.symbols +++ b/tests/baselines/reference/unknownSymbolOffContextualType1.symbols @@ -61,9 +61,9 @@ function getMaxWidth(elementNames: string[]) { }); var maxWidth = widths.reduce(function (a, b) { >maxWidth : Symbol(maxWidth, Decl(unknownSymbolOffContextualType1.ts, 17, 7)) ->widths.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>widths.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >widths : Symbol(widths, Decl(unknownSymbolOffContextualType1.ts, 14, 7)) ->reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >a : Symbol(a, Decl(unknownSymbolOffContextualType1.ts, 17, 43)) >b : Symbol(b, Decl(unknownSymbolOffContextualType1.ts, 17, 45)) diff --git a/tests/baselines/reference/unknownSymbolOffContextualType1.types b/tests/baselines/reference/unknownSymbolOffContextualType1.types index c6f05b69b7458..7df3bd52cc9a9 100644 --- a/tests/baselines/reference/unknownSymbolOffContextualType1.types +++ b/tests/baselines/reference/unknownSymbolOffContextualType1.types @@ -72,9 +72,9 @@ function getMaxWidth(elementNames: string[]) { var maxWidth = widths.reduce(function (a, b) { >maxWidth : any >widths.reduce(function (a, b) { return a > b ? a : b; }) : any ->widths.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>widths.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >widths : any[] ->reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } +>reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any): any; (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >function (a, b) { return a > b ? a : b; } : (a: any, b: any) => any >a : any >b : any From dc607c29b4f281d8734a70264525ecf3fbe64c25 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 9 Oct 2017 17:15:13 -0700 Subject: [PATCH 085/246] Fix 'this' capturing for dynamic import --- src/compiler/binder.ts | 6 ++ src/compiler/transformers/module/module.ts | 89 ++++++++++++++----- .../dynamicImportWithNestedThis_es2015.js | 37 ++++++++ ...dynamicImportWithNestedThis_es2015.symbols | 27 ++++++ .../dynamicImportWithNestedThis_es2015.types | 31 +++++++ .../dynamicImportWithNestedThis_es5.js | 39 ++++++++ .../dynamicImportWithNestedThis_es5.symbols | 27 ++++++ .../dynamicImportWithNestedThis_es5.types | 31 +++++++ .../dynamicImportWithNestedThis_es2015.ts | 14 +++ .../dynamicImportWithNestedThis_es5.ts | 14 +++ 10 files changed, 292 insertions(+), 23 deletions(-) create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es2015.js create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es2015.symbols create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es2015.types create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es5.js create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es5.symbols create mode 100644 tests/baselines/reference/dynamicImportWithNestedThis_es5.types create mode 100644 tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts create mode 100644 tests/cases/compiler/dynamicImportWithNestedThis_es5.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 9b977eb6bfcd1..48cace4484194 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2699,6 +2699,12 @@ namespace ts { if (expression.kind === SyntaxKind.ImportKeyword) { transformFlags |= TransformFlags.ContainsDynamicImport; + + // A dynamic 'import()' call that contains a lexical 'this' will + // require a captured 'this' when emitting down-level. + if (subtreeFlags & TransformFlags.ContainsLexicalThis) { + transformFlags |= TransformFlags.ContainsCapturedLexicalThis; + } } node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index ecbef6856497c..ba262bf2c59d0 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -561,46 +561,89 @@ namespace ts { // }); const resolve = createUniqueName("resolve"); const reject = createUniqueName("reject"); - return createNew( - createIdentifier("Promise"), - /*typeArguments*/ undefined, - [createFunctionExpression( + const parameters = [ + createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), + createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject) + ]; + const body = createBlock([ + createStatement( + createCall( + createIdentifier("require"), + /*typeArguments*/ undefined, + [createArrayLiteral([firstOrUndefined(node.arguments) || createOmittedExpression()]), resolve, reject] + ) + ) + ]); + + let func: FunctionExpression | ArrowFunction; + if (languageVersion >= ScriptTarget.ES2015) { + func = createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, + body); + } + else { + func = createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - [createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), - createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject)], + parameters, /*type*/ undefined, - createBlock([createStatement( - createCall( - createIdentifier("require"), - /*typeArguments*/ undefined, - [createArrayLiteral([firstOrUndefined(node.arguments) || createOmittedExpression()]), resolve, reject] - ))]) - )]); + body); + + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. + if (node.transformFlags & TransformFlags.ContainsLexicalThis) { + setEmitFlags(func, EmitFlags.CapturesThis); + } + } + + return createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); } - function transformImportCallExpressionCommonJS(node: ImportCall): Expression { + function transformImportCallExpressionCommonJS(node: ImportCall): Expression { // import("./blah") // emit as // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ // We have to wrap require in then callback so that require is done in asynchronously // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately - return createCall( - createPropertyAccess( - createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []), - "then"), - /*typeArguments*/ undefined, - [createFunctionExpression( + const promiseResolveCall = createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); + const requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, node.arguments); + + let func: FunctionExpression | ArrowFunction; + if (languageVersion >= ScriptTarget.ES2015) { + func = createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, + requireCall); + } + else { + func = createFunctionExpression( /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, - /*parameters*/ undefined, + /*parameters*/ [], /*type*/ undefined, - createBlock([createReturn(createCall(createIdentifier("require"), /*typeArguments*/ undefined, node.arguments))]) - )]); + createBlock([createReturn(requireCall)])); + + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. + if (node.transformFlags & TransformFlags.ContainsLexicalThis) { + setEmitFlags(func, EmitFlags.CapturesThis); + } + } + + return createCall(createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); } /** diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js new file mode 100644 index 0000000000000..86fba0c0b5d98 --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js @@ -0,0 +1,37 @@ +//// [dynamicImportWithNestedThis_es2015.ts] +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { + private _path = './other'; + + dynamic() { + return import(this._path); + } +} + +const c = new C(); +c.dynamic(); + +//// [dynamicImportWithNestedThis_es2015.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + // https://github.com/Microsoft/TypeScript/issues/17564 + class C { + constructor() { + this._path = './other'; + } + dynamic() { + return __syncRequire ? Promise.resolve().then(() => require(this._path)) : new Promise((resolve_1, reject_1) => { require([this._path], resolve_1, reject_1); }); + } + } + const c = new C(); + c.dynamic(); +}); diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es2015.symbols b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.symbols new file mode 100644 index 0000000000000..7043a071124b4 --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts === +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { +>C : Symbol(C, Decl(dynamicImportWithNestedThis_es2015.ts, 0, 0)) + + private _path = './other'; +>_path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es2015.ts, 1, 9)) + + dynamic() { +>dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es2015.ts, 2, 27)) + + return import(this._path); +>this._path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es2015.ts, 1, 9)) +>this : Symbol(C, Decl(dynamicImportWithNestedThis_es2015.ts, 0, 0)) +>_path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es2015.ts, 1, 9)) + } +} + +const c = new C(); +>c : Symbol(c, Decl(dynamicImportWithNestedThis_es2015.ts, 9, 5)) +>C : Symbol(C, Decl(dynamicImportWithNestedThis_es2015.ts, 0, 0)) + +c.dynamic(); +>c.dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es2015.ts, 2, 27)) +>c : Symbol(c, Decl(dynamicImportWithNestedThis_es2015.ts, 9, 5)) +>dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es2015.ts, 2, 27)) + diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es2015.types b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.types new file mode 100644 index 0000000000000..165929a43cfc2 --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.types @@ -0,0 +1,31 @@ +=== tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts === +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { +>C : C + + private _path = './other'; +>_path : string +>'./other' : "./other" + + dynamic() { +>dynamic : () => Promise + + return import(this._path); +>import(this._path) : Promise +>this._path : string +>this : this +>_path : string + } +} + +const c = new C(); +>c : C +>new C() : C +>C : typeof C + +c.dynamic(); +>c.dynamic() : Promise +>c.dynamic : () => Promise +>c : C +>dynamic : () => Promise + diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es5.js b/tests/baselines/reference/dynamicImportWithNestedThis_es5.js new file mode 100644 index 0000000000000..cde1979b25b54 --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es5.js @@ -0,0 +1,39 @@ +//// [dynamicImportWithNestedThis_es5.ts] +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { + private _path = './other'; + + dynamic() { + return import(this._path); + } +} + +const c = new C(); +c.dynamic(); + +//// [dynamicImportWithNestedThis_es5.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + // https://github.com/Microsoft/TypeScript/issues/17564 + var C = /** @class */ (function () { + function C() { + this._path = './other'; + } + C.prototype.dynamic = function () { + var _this = this; + return __syncRequire ? Promise.resolve().then(function () { return require(_this._path); }) : new Promise(function (resolve_1, reject_1) { require([_this._path], resolve_1, reject_1); }); + }; + return C; + }()); + var c = new C(); + c.dynamic(); +}); diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es5.symbols b/tests/baselines/reference/dynamicImportWithNestedThis_es5.symbols new file mode 100644 index 0000000000000..6a1275480307b --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es5.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/dynamicImportWithNestedThis_es5.ts === +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { +>C : Symbol(C, Decl(dynamicImportWithNestedThis_es5.ts, 0, 0)) + + private _path = './other'; +>_path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es5.ts, 1, 9)) + + dynamic() { +>dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es5.ts, 2, 27)) + + return import(this._path); +>this._path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es5.ts, 1, 9)) +>this : Symbol(C, Decl(dynamicImportWithNestedThis_es5.ts, 0, 0)) +>_path : Symbol(C._path, Decl(dynamicImportWithNestedThis_es5.ts, 1, 9)) + } +} + +const c = new C(); +>c : Symbol(c, Decl(dynamicImportWithNestedThis_es5.ts, 9, 5)) +>C : Symbol(C, Decl(dynamicImportWithNestedThis_es5.ts, 0, 0)) + +c.dynamic(); +>c.dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es5.ts, 2, 27)) +>c : Symbol(c, Decl(dynamicImportWithNestedThis_es5.ts, 9, 5)) +>dynamic : Symbol(C.dynamic, Decl(dynamicImportWithNestedThis_es5.ts, 2, 27)) + diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es5.types b/tests/baselines/reference/dynamicImportWithNestedThis_es5.types new file mode 100644 index 0000000000000..78b0f472971a6 --- /dev/null +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es5.types @@ -0,0 +1,31 @@ +=== tests/cases/compiler/dynamicImportWithNestedThis_es5.ts === +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { +>C : C + + private _path = './other'; +>_path : string +>'./other' : "./other" + + dynamic() { +>dynamic : () => Promise + + return import(this._path); +>import(this._path) : Promise +>this._path : string +>this : this +>_path : string + } +} + +const c = new C(); +>c : C +>new C() : C +>C : typeof C + +c.dynamic(); +>c.dynamic() : Promise +>c.dynamic : () => Promise +>c : C +>dynamic : () => Promise + diff --git a/tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts b/tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts new file mode 100644 index 0000000000000..3c7f293693165 --- /dev/null +++ b/tests/cases/compiler/dynamicImportWithNestedThis_es2015.ts @@ -0,0 +1,14 @@ +// @lib: es2015 +// @target: es2015 +// @module: umd +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { + private _path = './other'; + + dynamic() { + return import(this._path); + } +} + +const c = new C(); +c.dynamic(); \ No newline at end of file diff --git a/tests/cases/compiler/dynamicImportWithNestedThis_es5.ts b/tests/cases/compiler/dynamicImportWithNestedThis_es5.ts new file mode 100644 index 0000000000000..5740c3f669456 --- /dev/null +++ b/tests/cases/compiler/dynamicImportWithNestedThis_es5.ts @@ -0,0 +1,14 @@ +// @lib: es2015 +// @target: es5 +// @module: umd +// https://github.com/Microsoft/TypeScript/issues/17564 +class C { + private _path = './other'; + + dynamic() { + return import(this._path); + } +} + +const c = new C(); +c.dynamic(); \ No newline at end of file From aa22c56282021e19fe546d2f65f650836f826e3b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 9 Oct 2017 18:03:05 -0700 Subject: [PATCH 086/246] Swallow the directory watcher exceptions --- src/server/server.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index 6fab1a3d08ae4..7917f6fb544a6 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -753,10 +753,21 @@ namespace ts.server { const sys = ts.sys; // use watchGuard process on Windows when node version is 4 or later const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4; + const originalWatchDirectory = sys.watchDirectory; + const noopWatcher: FileWatcher = { close: noop }; + function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher { + try { + return originalWatchDirectory.call(sys, path, callback, recursive); + } + catch (e) { + logger.info(`Exception when creating directory watcher: ${e.message}`); + return noopWatcher; + } + } + if (useWatchGuard) { const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); const statusCache = createMap(); - const originalWatchDirectory = sys.watchDirectory; sys.watchDirectory = function (path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher { const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive); let status = cacheKey && statusCache.get(cacheKey); @@ -790,14 +801,17 @@ namespace ts.server { } if (status) { // this drive is safe to use - call real 'watchDirectory' - return originalWatchDirectory.call(sys, path, callback, recursive); + return watchDirectorySwallowingException(path, callback, recursive); } else { // this drive is unsafe - return no-op watcher - return { close() { } }; + return noopWatcher; } }; } + else { + sys.watchDirectory = watchDirectorySwallowingException; + } // Override sys.write because fs.writeSync is not reliable on Node 4 sys.write = (s: string) => writeMessage(new Buffer(s, "utf8")); From 98d58d651747702f2f9252ad93125026a770c565 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 9 Oct 2017 20:12:53 -0700 Subject: [PATCH 087/246] Handle project close to release all the script infos held by the project --- src/server/project.ts | 24 +++++++++---------- .../reference/api/tsserverlibrary.d.ts | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/server/project.ts b/src/server/project.ts index e8bfd7c1b75a5..db540ccfac235 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -495,25 +495,25 @@ namespace ts.server { close() { if (this.program) { - // if we have a program - release all files that are enlisted in program + // if we have a program - release all files that are enlisted in program but arent root + // The releasing of the roots happens later + // The project could have pending update remaining and hence the info could be in the files but not in program graph for (const f of this.program.getSourceFiles()) { - this.detachScriptInfo(f.fileName); + this.detachScriptInfoIfNotRoot(f.fileName); } } - if (!this.program || !this.languageServiceEnabled) { - // release all root files either if there is no program or language service is disabled. - // in the latter case set of root files can be larger than the set of files in program. - for (const root of this.rootFiles) { - root.detachFromProject(this); - } + // Release external files + forEach(this.externalFiles, externalFile => this.detachScriptInfoIfNotRoot(externalFile)); + // Always remove root files from the project + for (const root of this.rootFiles) { + root.detachFromProject(this); } this.rootFiles = undefined; this.rootFilesMap = undefined; + this.externalFiles = undefined; this.program = undefined; this.builder = undefined; - forEach(this.externalFiles, externalFile => this.detachScriptInfo(externalFile)); - this.externalFiles = undefined; this.resolutionCache.clear(); this.resolutionCache = undefined; this.cachedUnresolvedImportsPerFile = undefined; @@ -530,11 +530,11 @@ namespace ts.server { this.languageService = undefined; } - private detachScriptInfo(uncheckedFilename: string) { + private detachScriptInfoIfNotRoot(uncheckedFilename: string) { const info = this.projectService.getScriptInfo(uncheckedFilename); // We might not find the script info in case its not associated with the project any more // and project graph was not updated (eg delayed update graph in case of files changed/deleted on the disk) - if (info) { + if (info && !this.isRoot(info)) { info.detachFromProject(this); } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 7fe07813adcc5..0097ba249427c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7136,6 +7136,7 @@ declare namespace ts.server { getExternalFiles(): SortedReadonlyArray; getSourceFile(path: Path): SourceFile; close(): void; + private detachScriptInfoIfNotRoot(uncheckedFilename); isClosed(): boolean; hasRoots(): boolean; getRootFiles(): NormalizedPath[]; From dca6e33ac7ba655af0d27a9d2e9555424c9cc67e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 10 Oct 2017 10:03:18 -0700 Subject: [PATCH 088/246] baseline updates --- .../reference/importCallExpressionAsyncES6AMD.js | 10 +++++----- .../reference/importCallExpressionAsyncES6CJS.js | 10 +++++----- .../reference/importCallExpressionAsyncES6UMD.js | 10 +++++----- .../importCallExpressionCheckReturntype1.js | 6 +++--- .../importCallExpressionDeclarationEmit1.js | 10 +++++----- .../reference/importCallExpressionES6AMD.js | 12 ++++++------ .../reference/importCallExpressionES6CJS.js | 12 ++++++------ .../reference/importCallExpressionES6UMD.js | 12 ++++++------ .../importCallExpressionGrammarError.js | 10 +++++----- .../reference/importCallExpressionInAMD1.js | 8 ++++---- .../reference/importCallExpressionInAMD2.js | 2 +- .../reference/importCallExpressionInAMD3.js | 2 +- .../reference/importCallExpressionInAMD4.js | 12 ++++++------ .../reference/importCallExpressionInCJS1.js | 8 ++++---- .../reference/importCallExpressionInCJS2.js | 4 ++-- .../reference/importCallExpressionInCJS3.js | 2 +- .../reference/importCallExpressionInCJS4.js | 2 +- .../reference/importCallExpressionInCJS5.js | 12 ++++++------ .../importCallExpressionInExportEqualsAMD.js | 2 +- .../importCallExpressionInExportEqualsCJS.js | 2 +- .../importCallExpressionInExportEqualsUMD.js | 2 +- .../importCallExpressionInScriptContext1.js | 2 +- .../importCallExpressionInScriptContext2.js | 2 +- .../reference/importCallExpressionInUMD1.js | 8 ++++---- .../reference/importCallExpressionInUMD2.js | 2 +- .../reference/importCallExpressionInUMD3.js | 2 +- .../reference/importCallExpressionInUMD4.js | 12 ++++++------ .../importCallExpressionReturnPromiseOfAny.js | 16 ++++++++-------- ...tCallExpressionSpecifierNotStringTypeError.js | 10 +++++----- .../importCallExpressionWithTypeArgument.js | 4 ++-- 30 files changed, 104 insertions(+), 104 deletions(-) diff --git a/tests/baselines/reference/importCallExpressionAsyncES6AMD.js b/tests/baselines/reference/importCallExpressionAsyncES6AMD.js index 9819da8369bfd..7f86625bbfc67 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES6AMD.js +++ b/tests/baselines/reference/importCallExpressionAsyncES6AMD.js @@ -42,34 +42,34 @@ define(["require", "exports"], function (require, exports) { Object.defineProperty(exports, "__esModule", { value: true }); function fn() { return __awaiter(this, void 0, void 0, function* () { - const req = yield new Promise(function (resolve_1, reject_1) { require(['./test'], resolve_1, reject_1); }); // ONE + const req = yield new Promise((resolve_1, reject_1) => { require(['./test'], resolve_1, reject_1); }); // ONE }); } exports.fn = fn; class cl1 { m() { return __awaiter(this, void 0, void 0, function* () { - const req = yield new Promise(function (resolve_2, reject_2) { require(['./test'], resolve_2, reject_2); }); // TWO + const req = yield new Promise((resolve_2, reject_2) => { require(['./test'], resolve_2, reject_2); }); // TWO }); } } exports.cl1 = cl1; exports.obj = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield new Promise(function (resolve_3, reject_3) { require(['./test'], resolve_3, reject_3); }); // THREE + const req = yield new Promise((resolve_3, reject_3) => { require(['./test'], resolve_3, reject_3); }); // THREE }) }; class cl2 { constructor() { this.p = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield new Promise(function (resolve_4, reject_4) { require(['./test'], resolve_4, reject_4); }); // FOUR + const req = yield new Promise((resolve_4, reject_4) => { require(['./test'], resolve_4, reject_4); }); // FOUR }) }; } } exports.cl2 = cl2; exports.l = () => __awaiter(this, void 0, void 0, function* () { - const req = yield new Promise(function (resolve_5, reject_5) { require(['./test'], resolve_5, reject_5); }); // FIVE + const req = yield new Promise((resolve_5, reject_5) => { require(['./test'], resolve_5, reject_5); }); // FIVE }); }); diff --git a/tests/baselines/reference/importCallExpressionAsyncES6CJS.js b/tests/baselines/reference/importCallExpressionAsyncES6CJS.js index b512ae94b488a..20961f9633069 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES6CJS.js +++ b/tests/baselines/reference/importCallExpressionAsyncES6CJS.js @@ -41,33 +41,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", { value: true }); function fn() { return __awaiter(this, void 0, void 0, function* () { - const req = yield Promise.resolve().then(function () { return require('./test'); }); // ONE + const req = yield Promise.resolve().then(() => require('./test')); // ONE }); } exports.fn = fn; class cl1 { m() { return __awaiter(this, void 0, void 0, function* () { - const req = yield Promise.resolve().then(function () { return require('./test'); }); // TWO + const req = yield Promise.resolve().then(() => require('./test')); // TWO }); } } exports.cl1 = cl1; exports.obj = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield Promise.resolve().then(function () { return require('./test'); }); // THREE + const req = yield Promise.resolve().then(() => require('./test')); // THREE }) }; class cl2 { constructor() { this.p = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield Promise.resolve().then(function () { return require('./test'); }); // FOUR + const req = yield Promise.resolve().then(() => require('./test')); // FOUR }) }; } } exports.cl2 = cl2; exports.l = () => __awaiter(this, void 0, void 0, function* () { - const req = yield Promise.resolve().then(function () { return require('./test'); }); // FIVE + const req = yield Promise.resolve().then(() => require('./test')); // FIVE }); diff --git a/tests/baselines/reference/importCallExpressionAsyncES6UMD.js b/tests/baselines/reference/importCallExpressionAsyncES6UMD.js index f77d5150118a2..1d4aff0267060 100644 --- a/tests/baselines/reference/importCallExpressionAsyncES6UMD.js +++ b/tests/baselines/reference/importCallExpressionAsyncES6UMD.js @@ -51,34 +51,34 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", { value: true }); function fn() { return __awaiter(this, void 0, void 0, function* () { - const req = yield __syncRequire ? Promise.resolve().then(function () { return require('./test'); }) : new Promise(function (resolve_1, reject_1) { require(['./test'], resolve_1, reject_1); }); // ONE + const req = yield __syncRequire ? Promise.resolve().then(() => require('./test')) : new Promise((resolve_1, reject_1) => { require(['./test'], resolve_1, reject_1); }); // ONE }); } exports.fn = fn; class cl1 { m() { return __awaiter(this, void 0, void 0, function* () { - const req = yield __syncRequire ? Promise.resolve().then(function () { return require('./test'); }) : new Promise(function (resolve_2, reject_2) { require(['./test'], resolve_2, reject_2); }); // TWO + const req = yield __syncRequire ? Promise.resolve().then(() => require('./test')) : new Promise((resolve_2, reject_2) => { require(['./test'], resolve_2, reject_2); }); // TWO }); } } exports.cl1 = cl1; exports.obj = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield __syncRequire ? Promise.resolve().then(function () { return require('./test'); }) : new Promise(function (resolve_3, reject_3) { require(['./test'], resolve_3, reject_3); }); // THREE + const req = yield __syncRequire ? Promise.resolve().then(() => require('./test')) : new Promise((resolve_3, reject_3) => { require(['./test'], resolve_3, reject_3); }); // THREE }) }; class cl2 { constructor() { this.p = { m: () => __awaiter(this, void 0, void 0, function* () { - const req = yield __syncRequire ? Promise.resolve().then(function () { return require('./test'); }) : new Promise(function (resolve_4, reject_4) { require(['./test'], resolve_4, reject_4); }); // FOUR + const req = yield __syncRequire ? Promise.resolve().then(() => require('./test')) : new Promise((resolve_4, reject_4) => { require(['./test'], resolve_4, reject_4); }); // FOUR }) }; } } exports.cl2 = cl2; exports.l = () => __awaiter(this, void 0, void 0, function* () { - const req = yield __syncRequire ? Promise.resolve().then(function () { return require('./test'); }) : new Promise(function (resolve_5, reject_5) { require(['./test'], resolve_5, reject_5); }); // FIVE + const req = yield __syncRequire ? Promise.resolve().then(() => require('./test')) : new Promise((resolve_5, reject_5) => { require(['./test'], resolve_5, reject_5); }); // FIVE }); }); diff --git a/tests/baselines/reference/importCallExpressionCheckReturntype1.js b/tests/baselines/reference/importCallExpressionCheckReturntype1.js index facb691338851..3cc4893ff6720 100644 --- a/tests/baselines/reference/importCallExpressionCheckReturntype1.js +++ b/tests/baselines/reference/importCallExpressionCheckReturntype1.js @@ -30,6 +30,6 @@ exports.C = C; //// [1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -let p1 = Promise.resolve().then(function () { return require("./defaultPath"); }); -let p2 = Promise.resolve().then(function () { return require("./defaultPath"); }); -let p3 = Promise.resolve().then(function () { return require("./defaultPath"); }); +let p1 = Promise.resolve().then(() => require("./defaultPath")); +let p2 = Promise.resolve().then(() => require("./defaultPath")); +let p3 = Promise.resolve().then(() => require("./defaultPath")); diff --git a/tests/baselines/reference/importCallExpressionDeclarationEmit1.js b/tests/baselines/reference/importCallExpressionDeclarationEmit1.js index 07f95d3b3b244..721d85abe717a 100644 --- a/tests/baselines/reference/importCallExpressionDeclarationEmit1.js +++ b/tests/baselines/reference/importCallExpressionDeclarationEmit1.js @@ -15,12 +15,12 @@ function returnDynamicLoad(path: string) { } //// [importCallExpressionDeclarationEmit1.js] -Promise.resolve().then(function () { return require(getSpecifier()); }); -var p0 = Promise.resolve().then(function () { return require(`${directory}\${moduleFile}`); }); -var p1 = Promise.resolve().then(function () { return require(getSpecifier()); }); -const p2 = Promise.resolve().then(function () { return require(whatToLoad ? getSpecifier() : "defaulPath"); }); +Promise.resolve().then(() => require(getSpecifier())); +var p0 = Promise.resolve().then(() => require(`${directory}\${moduleFile}`)); +var p1 = Promise.resolve().then(() => require(getSpecifier())); +const p2 = Promise.resolve().then(() => require(whatToLoad ? getSpecifier() : "defaulPath")); function returnDynamicLoad(path) { - return Promise.resolve().then(function () { return require(path); }); + return Promise.resolve().then(() => require(path)); } diff --git a/tests/baselines/reference/importCallExpressionES6AMD.js b/tests/baselines/reference/importCallExpressionES6AMD.js index 08fec3b27fd24..1c5430c9f04b9 100644 --- a/tests/baselines/reference/importCallExpressionES6AMD.js +++ b/tests/baselines/reference/importCallExpressionES6AMD.js @@ -39,23 +39,23 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); - var p1 = new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); + var p1 = new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); p1.then(zero => { return zero.foo(); }); - exports.p2 = new Promise(function (resolve_3, reject_3) { require(["./0"], resolve_3, reject_3); }); + exports.p2 = new Promise((resolve_3, reject_3) => { require(["./0"], resolve_3, reject_3); }); function foo() { - const p2 = new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + const p2 = new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } class C { method() { - const loadAsync = new Promise(function (resolve_5, reject_5) { require(["./0"], resolve_5, reject_5); }); + const loadAsync = new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); } } class D { method() { - const loadAsync = new Promise(function (resolve_6, reject_6) { require(["./0"], resolve_6, reject_6); }); + const loadAsync = new Promise((resolve_6, reject_6) => { require(["./0"], resolve_6, reject_6); }); } } exports.D = D; diff --git a/tests/baselines/reference/importCallExpressionES6CJS.js b/tests/baselines/reference/importCallExpressionES6CJS.js index 28833e1747925..a1d8108bdeac4 100644 --- a/tests/baselines/reference/importCallExpressionES6CJS.js +++ b/tests/baselines/reference/importCallExpressionES6CJS.js @@ -36,23 +36,23 @@ exports.foo = foo; //// [1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -Promise.resolve().then(function () { return require("./0"); }); -var p1 = Promise.resolve().then(function () { return require("./0"); }); +Promise.resolve().then(() => require("./0")); +var p1 = Promise.resolve().then(() => require("./0")); p1.then(zero => { return zero.foo(); }); -exports.p2 = Promise.resolve().then(function () { return require("./0"); }); +exports.p2 = Promise.resolve().then(() => require("./0")); function foo() { - const p2 = Promise.resolve().then(function () { return require("./0"); }); + const p2 = Promise.resolve().then(() => require("./0")); } class C { method() { - const loadAsync = Promise.resolve().then(function () { return require("./0"); }); + const loadAsync = Promise.resolve().then(() => require("./0")); } } class D { method() { - const loadAsync = Promise.resolve().then(function () { return require("./0"); }); + const loadAsync = Promise.resolve().then(() => require("./0")); } } exports.D = D; diff --git a/tests/baselines/reference/importCallExpressionES6UMD.js b/tests/baselines/reference/importCallExpressionES6UMD.js index cc7dfef00749d..750a1a7cc0c8c 100644 --- a/tests/baselines/reference/importCallExpressionES6UMD.js +++ b/tests/baselines/reference/importCallExpressionES6UMD.js @@ -56,23 +56,23 @@ export class D { "use strict"; var __syncRequire = typeof module === "object" && typeof module.exports === "object"; Object.defineProperty(exports, "__esModule", { value: true }); - __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); - var p1 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); + var p1 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); p1.then(zero => { return zero.foo(); }); - exports.p2 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_3, reject_3) { require(["./0"], resolve_3, reject_3); }); + exports.p2 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_3, reject_3) => { require(["./0"], resolve_3, reject_3); }); function foo() { - const p2 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + const p2 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } class C { method() { - const loadAsync = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_5, reject_5) { require(["./0"], resolve_5, reject_5); }); + const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); } } class D { method() { - const loadAsync = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_6, reject_6) { require(["./0"], resolve_6, reject_6); }); + const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_6, reject_6) => { require(["./0"], resolve_6, reject_6); }); } } exports.D = D; diff --git a/tests/baselines/reference/importCallExpressionGrammarError.js b/tests/baselines/reference/importCallExpressionGrammarError.js index b30b0c9ddd550..e2ffc55577d3b 100644 --- a/tests/baselines/reference/importCallExpressionGrammarError.js +++ b/tests/baselines/reference/importCallExpressionGrammarError.js @@ -12,8 +12,8 @@ const p4 = import("pathToModule", "secondModule"); //// [importCallExpressionGrammarError.js] var a = ["./0"]; -Promise.resolve().then(function () { return require(...["PathModule"]); }); -var p1 = Promise.resolve().then(function () { return require(...a); }); -const p2 = Promise.resolve().then(function () { return require(); }); -const p3 = Promise.resolve().then(function () { return require(); }); -const p4 = Promise.resolve().then(function () { return require("pathToModule", "secondModule"); }); +Promise.resolve().then(() => require(...["PathModule"])); +var p1 = Promise.resolve().then(() => require(...a)); +const p2 = Promise.resolve().then(() => require()); +const p3 = Promise.resolve().then(() => require()); +const p4 = Promise.resolve().then(() => require("pathToModule", "secondModule")); diff --git a/tests/baselines/reference/importCallExpressionInAMD1.js b/tests/baselines/reference/importCallExpressionInAMD1.js index 5c858160353c7..64e5aee2ddae5 100644 --- a/tests/baselines/reference/importCallExpressionInAMD1.js +++ b/tests/baselines/reference/importCallExpressionInAMD1.js @@ -27,13 +27,13 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); - var p1 = new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); + var p1 = new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); p1.then(zero => { return zero.foo(); }); - exports.p2 = new Promise(function (resolve_3, reject_3) { require(["./0"], resolve_3, reject_3); }); + exports.p2 = new Promise((resolve_3, reject_3) => { require(["./0"], resolve_3, reject_3); }); function foo() { - const p2 = new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + const p2 = new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } }); diff --git a/tests/baselines/reference/importCallExpressionInAMD2.js b/tests/baselines/reference/importCallExpressionInAMD2.js index 7347e2f810562..0d3f0e08d216e 100644 --- a/tests/baselines/reference/importCallExpressionInAMD2.js +++ b/tests/baselines/reference/importCallExpressionInAMD2.js @@ -35,5 +35,5 @@ define(["require", "exports"], function (require, exports) { b.print(); }); } - foo(new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); })); + foo(new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); })); }); diff --git a/tests/baselines/reference/importCallExpressionInAMD3.js b/tests/baselines/reference/importCallExpressionInAMD3.js index 471f35a6415ae..07e7e92254189 100644 --- a/tests/baselines/reference/importCallExpressionInAMD3.js +++ b/tests/baselines/reference/importCallExpressionInAMD3.js @@ -26,7 +26,7 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports"], function (require, exports) { "use strict"; async function foo() { - class C extends (await new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); })).B { + class C extends (await new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); })).B { } var c = new C(); c.print(); diff --git a/tests/baselines/reference/importCallExpressionInAMD4.js b/tests/baselines/reference/importCallExpressionInAMD4.js index 43ba5afcd3055..2fe29e5ae065a 100644 --- a/tests/baselines/reference/importCallExpressionInAMD4.js +++ b/tests/baselines/reference/importCallExpressionInAMD4.js @@ -64,30 +64,30 @@ define(["require", "exports"], function (require, exports) { Object.defineProperty(exports, "__esModule", { value: true }); class C { constructor() { - this.myModule = new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); + this.myModule = new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); } method() { - const loadAsync = new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + const loadAsync = new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await new Promise(function (resolve_3, reject_3) { require(["./1"], resolve_3, reject_3); }); + let one = await new Promise((resolve_3, reject_3) => { require(["./1"], resolve_3, reject_3); }); console.log(one.backup()); }); } } class D { constructor() { - this.myModule = new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + this.myModule = new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } method() { - const loadAsync = new Promise(function (resolve_5, reject_5) { require(["./0"], resolve_5, reject_5); }); + const loadAsync = new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await new Promise(function (resolve_6, reject_6) { require(["./1"], resolve_6, reject_6); }); + let one = await new Promise((resolve_6, reject_6) => { require(["./1"], resolve_6, reject_6); }); console.log(one.backup()); }); } diff --git a/tests/baselines/reference/importCallExpressionInCJS1.js b/tests/baselines/reference/importCallExpressionInCJS1.js index 359e743144b7f..c814f5e567133 100644 --- a/tests/baselines/reference/importCallExpressionInCJS1.js +++ b/tests/baselines/reference/importCallExpressionInCJS1.js @@ -24,12 +24,12 @@ exports.foo = foo; //// [1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -Promise.resolve().then(function () { return require("./0"); }); -var p1 = Promise.resolve().then(function () { return require("./0"); }); +Promise.resolve().then(() => require("./0")); +var p1 = Promise.resolve().then(() => require("./0")); p1.then(zero => { return zero.foo(); }); -exports.p2 = Promise.resolve().then(function () { return require("./0"); }); +exports.p2 = Promise.resolve().then(() => require("./0")); function foo() { - const p2 = Promise.resolve().then(function () { return require("./0"); }); + const p2 = Promise.resolve().then(() => require("./0")); } diff --git a/tests/baselines/reference/importCallExpressionInCJS2.js b/tests/baselines/reference/importCallExpressionInCJS2.js index aa983a7a2fece..fb559cb11937a 100644 --- a/tests/baselines/reference/importCallExpressionInCJS2.js +++ b/tests/baselines/reference/importCallExpressionInCJS2.js @@ -32,9 +32,9 @@ exports.backup = backup; async function compute(promise) { let j = await promise; if (!j) { - j = await Promise.resolve().then(function () { return require("./1"); }); + j = await Promise.resolve().then(() => require("./1")); return j.backup(); } return j.foo(); } -compute(Promise.resolve().then(function () { return require("./0"); })); +compute(Promise.resolve().then(() => require("./0"))); diff --git a/tests/baselines/reference/importCallExpressionInCJS3.js b/tests/baselines/reference/importCallExpressionInCJS3.js index 2f956d9ac3aea..616fbc9c3f9f5 100644 --- a/tests/baselines/reference/importCallExpressionInCJS3.js +++ b/tests/baselines/reference/importCallExpressionInCJS3.js @@ -31,4 +31,4 @@ function foo(x) { b.print(); }); } -foo(Promise.resolve().then(function () { return require("./0"); })); +foo(Promise.resolve().then(() => require("./0"))); diff --git a/tests/baselines/reference/importCallExpressionInCJS4.js b/tests/baselines/reference/importCallExpressionInCJS4.js index 554a0b222abca..b88295110b83a 100644 --- a/tests/baselines/reference/importCallExpressionInCJS4.js +++ b/tests/baselines/reference/importCallExpressionInCJS4.js @@ -22,7 +22,7 @@ class B { exports.B = B; //// [2.js] async function foo() { - class C extends (await Promise.resolve().then(function () { return require("./0"); })).B { + class C extends (await Promise.resolve().then(() => require("./0"))).B { } var c = new C(); c.print(); diff --git a/tests/baselines/reference/importCallExpressionInCJS5.js b/tests/baselines/reference/importCallExpressionInCJS5.js index eeb4db275fa37..b32b0e52c50f7 100644 --- a/tests/baselines/reference/importCallExpressionInCJS5.js +++ b/tests/baselines/reference/importCallExpressionInCJS5.js @@ -59,30 +59,30 @@ exports.backup = backup; Object.defineProperty(exports, "__esModule", { value: true }); class C { constructor() { - this.myModule = Promise.resolve().then(function () { return require("./0"); }); + this.myModule = Promise.resolve().then(() => require("./0")); } method() { - const loadAsync = Promise.resolve().then(function () { return require("./0"); }); + const loadAsync = Promise.resolve().then(() => require("./0")); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await Promise.resolve().then(function () { return require("./1"); }); + let one = await Promise.resolve().then(() => require("./1")); console.log(one.backup()); }); } } class D { constructor() { - this.myModule = Promise.resolve().then(function () { return require("./0"); }); + this.myModule = Promise.resolve().then(() => require("./0")); } method() { - const loadAsync = Promise.resolve().then(function () { return require("./0"); }); + const loadAsync = Promise.resolve().then(() => require("./0")); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await Promise.resolve().then(function () { return require("./1"); }); + let one = await Promise.resolve().then(() => require("./1")); console.log(one.backup()); }); } diff --git a/tests/baselines/reference/importCallExpressionInExportEqualsAMD.js b/tests/baselines/reference/importCallExpressionInExportEqualsAMD.js index f2fda1fadd79f..1fcef2bde3941 100644 --- a/tests/baselines/reference/importCallExpressionInExportEqualsAMD.js +++ b/tests/baselines/reference/importCallExpressionInExportEqualsAMD.js @@ -17,6 +17,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports"], function (require, exports) { "use strict"; return async function () { - const something = await new Promise(function (resolve_1, reject_1) { require(["./something"], resolve_1, reject_1); }); + const something = await new Promise((resolve_1, reject_1) => { require(["./something"], resolve_1, reject_1); }); }; }); diff --git a/tests/baselines/reference/importCallExpressionInExportEqualsCJS.js b/tests/baselines/reference/importCallExpressionInExportEqualsCJS.js index 5d7e28161164d..72e3a0ec0af9b 100644 --- a/tests/baselines/reference/importCallExpressionInExportEqualsCJS.js +++ b/tests/baselines/reference/importCallExpressionInExportEqualsCJS.js @@ -14,5 +14,5 @@ module.exports = 42; //// [index.js] "use strict"; module.exports = async function () { - const something = await Promise.resolve().then(function () { return require("./something"); }); + const something = await Promise.resolve().then(() => require("./something")); }; diff --git a/tests/baselines/reference/importCallExpressionInExportEqualsUMD.js b/tests/baselines/reference/importCallExpressionInExportEqualsUMD.js index e0c6e2a925fd7..5f70891b09e8e 100644 --- a/tests/baselines/reference/importCallExpressionInExportEqualsUMD.js +++ b/tests/baselines/reference/importCallExpressionInExportEqualsUMD.js @@ -34,6 +34,6 @@ export = async function() { "use strict"; var __syncRequire = typeof module === "object" && typeof module.exports === "object"; return async function () { - const something = await (__syncRequire ? Promise.resolve().then(function () { return require("./something"); }) : new Promise(function (resolve_1, reject_1) { require(["./something"], resolve_1, reject_1); })); + const something = await (__syncRequire ? Promise.resolve().then(() => require("./something")) : new Promise((resolve_1, reject_1) => { require(["./something"], resolve_1, reject_1); })); }; }); diff --git a/tests/baselines/reference/importCallExpressionInScriptContext1.js b/tests/baselines/reference/importCallExpressionInScriptContext1.js index 2c2d2f904d50c..53c6118f61bf1 100644 --- a/tests/baselines/reference/importCallExpressionInScriptContext1.js +++ b/tests/baselines/reference/importCallExpressionInScriptContext1.js @@ -13,5 +13,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); function foo() { return "foo"; } exports.foo = foo; //// [1.js] -var p1 = Promise.resolve().then(function () { return require("./0"); }); +var p1 = Promise.resolve().then(() => require("./0")); function arguments() { } // this is allow as the file doesn't have implicit "use strict" diff --git a/tests/baselines/reference/importCallExpressionInScriptContext2.js b/tests/baselines/reference/importCallExpressionInScriptContext2.js index 6b6e0109fdad3..4a0d4a1bf5a98 100644 --- a/tests/baselines/reference/importCallExpressionInScriptContext2.js +++ b/tests/baselines/reference/importCallExpressionInScriptContext2.js @@ -15,5 +15,5 @@ function foo() { return "foo"; } exports.foo = foo; //// [1.js] "use strict"; -var p1 = Promise.resolve().then(function () { return require("./0"); }); +var p1 = Promise.resolve().then(() => require("./0")); function arguments() { } diff --git a/tests/baselines/reference/importCallExpressionInUMD1.js b/tests/baselines/reference/importCallExpressionInUMD1.js index ee99468f7f33a..597e68e2d6f71 100644 --- a/tests/baselines/reference/importCallExpressionInUMD1.js +++ b/tests/baselines/reference/importCallExpressionInUMD1.js @@ -44,13 +44,13 @@ function foo() { "use strict"; var __syncRequire = typeof module === "object" && typeof module.exports === "object"; Object.defineProperty(exports, "__esModule", { value: true }); - __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); - var p1 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); + var p1 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); p1.then(zero => { return zero.foo(); }); - exports.p2 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_3, reject_3) { require(["./0"], resolve_3, reject_3); }); + exports.p2 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_3, reject_3) => { require(["./0"], resolve_3, reject_3); }); function foo() { - const p2 = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + const p2 = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } }); diff --git a/tests/baselines/reference/importCallExpressionInUMD2.js b/tests/baselines/reference/importCallExpressionInUMD2.js index db8b87a2f799e..516800968c13d 100644 --- a/tests/baselines/reference/importCallExpressionInUMD2.js +++ b/tests/baselines/reference/importCallExpressionInUMD2.js @@ -52,5 +52,5 @@ foo(import("./0")); b.print(); }); } - foo(__syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); })); + foo(__syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); })); }); diff --git a/tests/baselines/reference/importCallExpressionInUMD3.js b/tests/baselines/reference/importCallExpressionInUMD3.js index 41106e3ab781a..57d200ca70ca3 100644 --- a/tests/baselines/reference/importCallExpressionInUMD3.js +++ b/tests/baselines/reference/importCallExpressionInUMD3.js @@ -43,7 +43,7 @@ foo(); "use strict"; var __syncRequire = typeof module === "object" && typeof module.exports === "object"; async function foo() { - class C extends (await (__syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }))).B { + class C extends (await (__syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }))).B { } var c = new C(); c.print(); diff --git a/tests/baselines/reference/importCallExpressionInUMD4.js b/tests/baselines/reference/importCallExpressionInUMD4.js index 477a7826bc07d..70a574f03028e 100644 --- a/tests/baselines/reference/importCallExpressionInUMD4.js +++ b/tests/baselines/reference/importCallExpressionInUMD4.js @@ -89,30 +89,30 @@ export class D { Object.defineProperty(exports, "__esModule", { value: true }); class C { constructor() { - this.myModule = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_1, reject_1) { require(["./0"], resolve_1, reject_1); }); + this.myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_1, reject_1) => { require(["./0"], resolve_1, reject_1); }); } method() { - const loadAsync = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_2, reject_2) { require(["./0"], resolve_2, reject_2); }); + const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_2, reject_2) => { require(["./0"], resolve_2, reject_2); }); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await (__syncRequire ? Promise.resolve().then(function () { return require("./1"); }) : new Promise(function (resolve_3, reject_3) { require(["./1"], resolve_3, reject_3); })); + let one = await (__syncRequire ? Promise.resolve().then(() => require("./1")) : new Promise((resolve_3, reject_3) => { require(["./1"], resolve_3, reject_3); })); console.log(one.backup()); }); } } class D { constructor() { - this.myModule = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_4, reject_4) { require(["./0"], resolve_4, reject_4); }); + this.myModule = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_4, reject_4) => { require(["./0"], resolve_4, reject_4); }); } method() { - const loadAsync = __syncRequire ? Promise.resolve().then(function () { return require("./0"); }) : new Promise(function (resolve_5, reject_5) { require(["./0"], resolve_5, reject_5); }); + const loadAsync = __syncRequire ? Promise.resolve().then(() => require("./0")) : new Promise((resolve_5, reject_5) => { require(["./0"], resolve_5, reject_5); }); this.myModule.then(Zero => { console.log(Zero.foo()); }, async (err) => { console.log(err); - let one = await (__syncRequire ? Promise.resolve().then(function () { return require("./1"); }) : new Promise(function (resolve_6, reject_6) { require(["./1"], resolve_6, reject_6); })); + let one = await (__syncRequire ? Promise.resolve().then(() => require("./1")) : new Promise((resolve_6, reject_6) => { require(["./1"], resolve_6, reject_6); })); console.log(one.backup()); }); } diff --git a/tests/baselines/reference/importCallExpressionReturnPromiseOfAny.js b/tests/baselines/reference/importCallExpressionReturnPromiseOfAny.js index 728d663695331..8c94510b6095b 100644 --- a/tests/baselines/reference/importCallExpressionReturnPromiseOfAny.js +++ b/tests/baselines/reference/importCallExpressionReturnPromiseOfAny.js @@ -42,20 +42,20 @@ exports.C = C; //// [1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -Promise.resolve().then(function () { return require(`${directory}\${moduleFile}`); }); -Promise.resolve().then(function () { return require(getSpecifier()); }); -var p1 = Promise.resolve().then(function () { return require(ValidSomeCondition() ? "./0" : "externalModule"); }); -var p1 = Promise.resolve().then(function () { return require(getSpecifier()); }); -var p11 = Promise.resolve().then(function () { return require(getSpecifier()); }); -const p2 = Promise.resolve().then(function () { return require(whatToLoad ? getSpecifier() : "defaulPath"); }); +Promise.resolve().then(() => require(`${directory}\${moduleFile}`)); +Promise.resolve().then(() => require(getSpecifier())); +var p1 = Promise.resolve().then(() => require(ValidSomeCondition() ? "./0" : "externalModule")); +var p1 = Promise.resolve().then(() => require(getSpecifier())); +var p11 = Promise.resolve().then(() => require(getSpecifier())); +const p2 = Promise.resolve().then(() => require(whatToLoad ? getSpecifier() : "defaulPath")); p1.then(zero => { return zero.foo(); // ok, zero is any }); let j; -var p3 = Promise.resolve().then(function () { return require(j = getSpecifier()); }); +var p3 = Promise.resolve().then(() => require(j = getSpecifier())); function* loadModule(directories) { for (const directory of directories) { const path = `${directory}\moduleFile`; - Promise.resolve().then(function () { return require(yield path); }); + Promise.resolve().then(() => require(yield path)); } } diff --git a/tests/baselines/reference/importCallExpressionSpecifierNotStringTypeError.js b/tests/baselines/reference/importCallExpressionSpecifierNotStringTypeError.js index dde35d8048bb0..5e2ace1c4017f 100644 --- a/tests/baselines/reference/importCallExpressionSpecifierNotStringTypeError.js +++ b/tests/baselines/reference/importCallExpressionSpecifierNotStringTypeError.js @@ -15,11 +15,11 @@ var p4 = import(()=>"PathToModule"); //// [importCallExpressionSpecifierNotStringTypeError.js] // Error specifier is not assignable to string -Promise.resolve().then(function () { return require(getSpecifier()); }); -var p1 = Promise.resolve().then(function () { return require(getSpecifier()); }); -const p2 = Promise.resolve().then(function () { return require(whatToLoad ? getSpecifier() : "defaulPath"); }); +Promise.resolve().then(() => require(getSpecifier())); +var p1 = Promise.resolve().then(() => require(getSpecifier())); +const p2 = Promise.resolve().then(() => require(whatToLoad ? getSpecifier() : "defaulPath")); p1.then(zero => { return zero.foo(); // ok, zero is any }); -var p3 = Promise.resolve().then(function () { return require(["path1", "path2"]); }); -var p4 = Promise.resolve().then(function () { return require(() => "PathToModule"); }); +var p3 = Promise.resolve().then(() => require(["path1", "path2"])); +var p4 = Promise.resolve().then(() => require(() => "PathToModule")); diff --git a/tests/baselines/reference/importCallExpressionWithTypeArgument.js b/tests/baselines/reference/importCallExpressionWithTypeArgument.js index 2915669eae584..885992a798b73 100644 --- a/tests/baselines/reference/importCallExpressionWithTypeArgument.js +++ b/tests/baselines/reference/importCallExpressionWithTypeArgument.js @@ -15,5 +15,5 @@ function foo() { return "foo"; } exports.foo = foo; //// [1.js] "use strict"; -var p1 = Promise.resolve().then(function () { return require("./0"); }); // error -var p2 = Promise.resolve().then(function () { return require("./0"); }); // error +var p1 = Promise.resolve().then(() => require("./0")); // error +var p2 = Promise.resolve().then(() => require("./0")); // error From 3eeb54861d310a37518e81642bee77120c097e00 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Oct 2017 10:53:43 -0700 Subject: [PATCH 089/246] Fix invalid cast (#18821) --- src/compiler/binder.ts | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 48cace4484194..4cacb5765db35 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2271,16 +2271,13 @@ namespace ts { function isExportsOrModuleExportsOrAlias(node: Node): boolean { return isExportsIdentifier(node) || isModuleExportsPropertyAccessExpression(node) || - isNameOfExportsOrModuleExportsAliasDeclaration(node); + isIdentifier(node) && isNameOfExportsOrModuleExportsAliasDeclaration(node); } - function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) { - if (isIdentifier(node)) { - const symbol = lookupSymbolForName(node.escapedText); - return symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && - symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(symbol.valueDeclaration.initializer); - } - return false; + function isNameOfExportsOrModuleExportsAliasDeclaration(node: Identifier): boolean { + const symbol = lookupSymbolForName(node.escapedText); + return symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && + symbol.valueDeclaration.initializer && isExportsOrModuleExportsOrAliasOrAssignment(symbol.valueDeclaration.initializer); } function isExportsOrModuleExportsOrAliasOrAssignment(node: Node): boolean { @@ -2354,20 +2351,22 @@ namespace ts { // Look up the function in the local scope, since prototype assignments should // follow the function declaration const leftSideOfAssignment = node.left as PropertyAccessExpression; - const target = leftSideOfAssignment.expression as Identifier; + const target = leftSideOfAssignment.expression; - // Fix up parent pointers since we're going to use these nodes before we bind into them - leftSideOfAssignment.parent = node; - target.parent = leftSideOfAssignment; + if (isIdentifier(target)) { + // Fix up parent pointers since we're going to use these nodes before we bind into them + leftSideOfAssignment.parent = node; + target.parent = leftSideOfAssignment; - if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) { - // This can be an alias for the 'exports' or 'module.exports' names, e.g. - // var util = module.exports; - // util.property = function ... - bindExportsPropertyAssignment(node); - } - else { - bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false); + if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) { + // This can be an alias for the 'exports' or 'module.exports' names, e.g. + // var util = module.exports; + // util.property = function ... + bindExportsPropertyAssignment(node); + } + else { + bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false); + } } } From 9ccc1b48873bb2cd1e1a0cf9eabc0232c26c200d Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Oct 2017 10:54:29 -0700 Subject: [PATCH 090/246] Remove unnecessary uses of `any` in shims.ts (#19038) --- src/services/shims.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/services/shims.ts b/src/services/shims.ts index 737db44b83f34..9d4baccc3c4e0 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -16,7 +16,7 @@ /// /* @internal */ -let debugObjectHost = (function (this: any) { return this; })(); +let debugObjectHost: { CollectGarbage(): void } = (function (this: any) { return this; })(); // We need to use 'null' to interface with the managed side. /* tslint:disable:no-null-keyword */ @@ -119,13 +119,13 @@ namespace ts { } export interface Shim { - dispose(_dummy: any): void; + dispose(_dummy: {}): void; } export interface LanguageServiceShim extends Shim { languageService: LanguageService; - dispose(_dummy: any): void; + dispose(_dummy: {}): void; refresh(throwOnError: boolean): void; @@ -417,7 +417,7 @@ namespace ts { return this.shimHost.getScriptVersion(fileName); } - public getLocalizedDiagnosticMessages(): any { + public getLocalizedDiagnosticMessages() { const diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages(); if (diagnosticMessagesJson === null || diagnosticMessagesJson === "") { return null; @@ -515,7 +515,7 @@ namespace ts { } } - function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): any { + function simpleForwardCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): {} { let start: number; if (logPerformance) { logger.log(actionDescription); @@ -539,14 +539,14 @@ namespace ts { return result; } - function forwardJSONCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): string { + function forwardJSONCall(logger: Logger, actionDescription: string, action: () => {}, logPerformance: boolean): string { return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance); } function forwardCall(logger: Logger, actionDescription: string, returnJson: boolean, action: () => T, logPerformance: boolean): T | string { try { const result = simpleForwardCall(logger, actionDescription, action, logPerformance); - return returnJson ? JSON.stringify({ result }) : result; + return returnJson ? JSON.stringify({ result }) : result as T; } catch (err) { if (err instanceof OperationCanceledException) { @@ -563,7 +563,7 @@ namespace ts { constructor(private factory: ShimFactory) { factory.registerShim(this); } - public dispose(_dummy: any): void { + public dispose(_dummy: {}): void { this.factory.unregisterShim(this); } } @@ -601,7 +601,7 @@ namespace ts { this.logger = this.host; } - public forwardJSONCall(actionDescription: string, action: () => any): string { + public forwardJSONCall(actionDescription: string, action: () => {}): string { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); } @@ -611,7 +611,7 @@ namespace ts { * Ensure (almost) deterministic release of internal Javascript resources when * some external native objects holds onto us (e.g. Com/Interop). */ - public dispose(dummy: any): void { + public dispose(dummy: {}): void { this.logger.log("dispose()"); this.languageService.dispose(); this.languageService = null; @@ -635,7 +635,7 @@ namespace ts { public refresh(throwOnError: boolean): void { this.forwardJSONCall( `refresh(${throwOnError})`, - () => null + () => null ); } @@ -644,7 +644,7 @@ namespace ts { "cleanupSemanticCache()", () => { this.languageService.cleanupSemanticCache(); - return null; + return null; }); } @@ -980,13 +980,13 @@ namespace ts { ); } - public getEmitOutputObject(fileName: string): any { + public getEmitOutputObject(fileName: string): EmitOutput { return forwardCall( this.logger, `getEmitOutput('${fileName}')`, /*returnJson*/ false, () => this.languageService.getEmitOutput(fileName), - this.logPerformance); + this.logPerformance) as EmitOutput; } } @@ -1030,7 +1030,7 @@ namespace ts { super(factory); } - private forwardJSONCall(actionDescription: string, action: () => any): any { + private forwardJSONCall(actionDescription: string, action: () => {}): string { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); } @@ -1221,7 +1221,7 @@ namespace ts { // Here we expose the TypeScript services as an external module // so that it may be consumed easily like a node module. - declare const module: any; + declare const module: { exports: {} }; if (typeof module !== "undefined" && module.exports) { module.exports = ts; } From 3171d082a6c126a0930e3b94cb2f791e2d059069 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 10:52:29 -0700 Subject: [PATCH 091/246] Handle the case of completion of class member when member name is being edited Fixes #17977 --- src/services/completions.ts | 5 +++ .../completionEntryForClassMembers3.ts | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/cases/fourslash/completionEntryForClassMembers3.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 44ad611de79aa..c222425693709 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1195,6 +1195,11 @@ namespace ts.Completions { if (isClassLike(location)) { return location; } + // class c { method() { } b| } + if (isFromClassElementDeclaration(location) && + (location.parent as ClassElement).name === location) { + return location.parent.parent as ClassLikeDeclaration; + } break; default: diff --git a/tests/cases/fourslash/completionEntryForClassMembers3.ts b/tests/cases/fourslash/completionEntryForClassMembers3.ts new file mode 100644 index 0000000000000..a27c5959e6de1 --- /dev/null +++ b/tests/cases/fourslash/completionEntryForClassMembers3.ts @@ -0,0 +1,32 @@ +/// + +////interface IFoo { +//// bar(): void; +////} +////class Foo1 implements IFoo { +//// zap() { } +//// /*1*/ +////} +////class Foo2 implements IFoo { +//// zap() { } +//// b/*2*/() { } +////} +////class Foo3 implements IFoo { +//// zap() { } +//// b/*3*/: any; +////} +const allowedKeywordCount = verify.allowedClassElementKeywords.length; +function verifyHasBar() { + verify.completionListContains("bar", "(method) IFoo.bar(): void", /*documentation*/ undefined, "method"); + verify.completionListContainsClassElementKeywords(); + verify.completionListCount(allowedKeywordCount + 1); +} + +goTo.marker("1"); +verifyHasBar(); +edit.insert("b"); +verifyHasBar(); +goTo.marker("2"); +verifyHasBar(); +goTo.marker("3"); +verifyHasBar(); \ No newline at end of file From b839e17e178d27e4ffbc97121246c14d1f07149a Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Oct 2017 11:27:53 -0700 Subject: [PATCH 092/246] Improve JSDoc @augments diagnostics (#19011) --- src/compiler/checker.ts | 4 ++-- src/compiler/diagnosticMessages.json | 4 ++-- tests/baselines/reference/jsdocAugments_notAClass.errors.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d47a77a74401a..2cad5dbf65273 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20034,7 +20034,7 @@ namespace ts { function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void { const classLike = getJSDocHost(node); if (!isClassDeclaration(classLike) && !isClassExpression(classLike)) { - error(classLike, Diagnostics.JSDoc_augments_is_not_attached_to_a_class_declaration); + error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName)); return; } @@ -20049,7 +20049,7 @@ namespace ts { if (extend) { const className = getIdentifierFromEntityNameExpression(extend.expression); if (className && name.escapedText !== className.escapedText) { - error(name, Diagnostics.JSDoc_augments_0_does_not_match_the_extends_1_clause, idText(name), idText(className)); + error(name, Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, idText(node.tagName), idText(name), idText(className)); } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 91ad9e52bfd60..e5e7b7748848a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3519,11 +3519,11 @@ "category": "Error", "code": 8021 }, - "JSDoc '@augments' is not attached to a class declaration.": { + "JSDoc '@{0}' is not attached to a class.": { "category": "Error", "code": 8022 }, - "JSDoc '@augments {0}' does not match the 'extends {1}' clause.": { + "JSDoc '@{0} {1}' does not match the 'extends {2}' clause.": { "category": "Error", "code": 8023 }, diff --git a/tests/baselines/reference/jsdocAugments_notAClass.errors.txt b/tests/baselines/reference/jsdocAugments_notAClass.errors.txt index 9f8528f0cd804..daf20aaf884b1 100644 --- a/tests/baselines/reference/jsdocAugments_notAClass.errors.txt +++ b/tests/baselines/reference/jsdocAugments_notAClass.errors.txt @@ -1,4 +1,4 @@ -/b.js(3,10): error TS8022: JSDoc '@augments' is not attached to a class declaration. +/b.js(3,10): error TS8022: JSDoc '@augments' is not attached to a class. ==== /b.js (1 errors) ==== @@ -6,5 +6,5 @@ /** @augments A */ function b() {} ~ -!!! error TS8022: JSDoc '@augments' is not attached to a class declaration. +!!! error TS8022: JSDoc '@augments' is not attached to a class. \ No newline at end of file From 927ffefcf43727bf3168ee2e10fe7ed30e731a9f Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Oct 2017 11:28:05 -0700 Subject: [PATCH 093/246] Replace more 'verify.rangeAfterCodeFix' with 'verify.codeFix' (#18800) --- src/compiler/diagnosticMessages.json | 2 +- src/harness/fourslash.ts | 2 +- .../codeFixChangeExtendsToImplements.ts | 5 +- ...angeExtendsToImplementsAbstractModifier.ts | 6 ++- ...eFixChangeExtendsToImplementsTypeParams.ts | 5 +- ...xChangeExtendsToImplementsWithDecorator.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax1.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax10.ts | 8 ++- .../fourslash/codeFixChangeJSDocSyntax11.ts | 8 ++- .../fourslash/codeFixChangeJSDocSyntax12.ts | 8 ++- .../fourslash/codeFixChangeJSDocSyntax13.ts | 8 ++- .../fourslash/codeFixChangeJSDocSyntax14.ts | 7 ++- .../fourslash/codeFixChangeJSDocSyntax15.ts | 7 ++- .../fourslash/codeFixChangeJSDocSyntax16.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax17.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax18.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax19.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax2.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax20.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax21.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax22.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax23.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax24.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax25.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax26.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax27.ts | 8 ++- .../fourslash/codeFixChangeJSDocSyntax3.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax4.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax5.ts | 7 ++- .../fourslash/codeFixChangeJSDocSyntax6.ts | 6 ++- .../fourslash/codeFixChangeJSDocSyntax7.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax8.ts | 5 +- .../fourslash/codeFixChangeJSDocSyntax9.ts | 5 +- ...ClassImplementClassFunctionVoidInferred.ts | 21 ++++---- ...prExtendsAbstractExpressionWithTypeArgs.ts | 23 ++++---- ...assExtendAbstractExpressionWithTypeArgs.ts | 23 ++++---- .../codeFixClassExtendAbstractGetterSetter.ts | 53 ++++++++++--------- .../codeFixClassExtendAbstractMethod.ts | 33 ++++++------ .../codeFixClassExtendAbstractMethodThis.ts | 19 ++++--- ...stractMethodTypeParamsInstantiateNumber.ts | 18 ++++--- ...endAbstractMethodTypeParamsInstantiateU.ts | 18 ++++--- .../codeFixClassExtendAbstractProperty.ts | 19 ++++--- tests/cases/fourslash/unusedMethodInClass1.ts | 11 ++-- tests/cases/fourslash/unusedMethodInClass2.ts | 12 +++-- tests/cases/fourslash/unusedMethodInClass3.ts | 11 ++-- tests/cases/fourslash/unusedMethodInClass4.ts | 8 ++- tests/cases/fourslash/unusedMethodInClass5.ts | 11 ++-- tests/cases/fourslash/unusedMethodInClass6.ts | 11 ++-- .../fourslash/unusedNamespaceInNamespace.ts | 16 +++--- .../unusedParameterInConstructor1.ts | 6 ++- ...sedParameterInConstructor1AddUnderscore.ts | 6 ++- .../unusedParameterInConstructor2.ts | 6 ++- .../unusedParameterInConstructor3.ts | 6 ++- .../unusedParameterInConstructor4.ts | 6 ++- .../fourslash/unusedParameterInFunction1.ts | 6 ++- ...unusedParameterInFunction1AddUnderscore.ts | 6 ++- .../fourslash/unusedParameterInFunction2.ts | 6 ++- .../fourslash/unusedParameterInFunction3.ts | 6 ++- .../fourslash/unusedParameterInFunction4.ts | 6 ++- .../fourslash/unusedParameterInLambda1.ts | 6 ++- .../unusedParameterInLambda1AddUnderscore.ts | 6 ++- .../fourslash/unusedTypeAliasInNamespace1.ts | 15 +++--- .../fourslash/unusedTypeParametersInClass1.ts | 5 +- .../fourslash/unusedTypeParametersInClass2.ts | 5 +- .../fourslash/unusedTypeParametersInClass3.ts | 5 +- .../unusedTypeParametersInFunction1.ts | 5 +- .../unusedTypeParametersInFunction2.ts | 5 +- .../unusedTypeParametersInFunction3.ts | 5 +- .../unusedTypeParametersInInterface1.ts | 5 +- .../unusedTypeParametersInLambda1.ts | 5 +- .../unusedTypeParametersInLambda2.ts | 5 +- .../unusedTypeParametersInLambda3.ts | 5 +- .../unusedTypeParametersInLambda4.ts | 5 +- .../unusedTypeParametersInMethod1.ts | 5 +- .../unusedTypeParametersInMethod2.ts | 5 +- .../unusedTypeParametersInMethods1.ts | 5 +- .../cases/fourslash/unusedVariableInBlocks.ts | 15 +++--- .../cases/fourslash/unusedVariableInClass1.ts | 5 +- .../cases/fourslash/unusedVariableInClass2.ts | 5 +- .../cases/fourslash/unusedVariableInClass3.ts | 5 +- .../fourslash/unusedVariableInForLoop1FS.ts | 6 ++- .../fourslash/unusedVariableInForLoop2FS.ts | 5 +- .../fourslash/unusedVariableInForLoop3FS.ts | 5 +- .../fourslash/unusedVariableInForLoop4FS.ts | 5 +- ...unusedVariableInForLoop5FSAddUnderscore.ts | 5 +- .../fourslash/unusedVariableInForLoop6FS.ts | 7 ++- ...unusedVariableInForLoop6FSAddUnderscore.ts | 6 ++- .../fourslash/unusedVariableInForLoop7FS.ts | 7 ++- .../fourslash/unusedVariableInModule1.ts | 5 +- .../fourslash/unusedVariableInModule2.ts | 5 +- .../fourslash/unusedVariableInModule3.ts | 5 +- .../fourslash/unusedVariableInModule4.ts | 6 ++- .../fourslash/unusedVariableInNamespace1.ts | 5 +- .../fourslash/unusedVariableInNamespace2.ts | 5 +- .../fourslash/unusedVariableInNamespace3.ts | 5 +- 95 files changed, 545 insertions(+), 224 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e5e7b7748848a..251e84ca8f4c6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3661,7 +3661,7 @@ "category": "Message", "code": 90013 }, - "Change {0} to {1}.": { + "Change '{0}' to '{1}'.": { "category": "Message", "code": 90014 }, diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index debb729067898..de6d92eda05ed 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2381,7 +2381,7 @@ Actual: ${stringify(fullActual)}`); })); return ts.flatMap(ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties), diagnostic => { - if (errorCode && errorCode !== diagnostic.code) { + if (errorCode !== undefined && errorCode !== diagnostic.code) { return; } diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts index bfaedf2818a9e..bf3b8b7b8a48c 100644 --- a/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplements.ts @@ -3,4 +3,7 @@ //// interface I {} //// [|/* */ class /* */ C /* */ extends /* */ I|]{} -verify.rangeAfterCodeFix("/* */ class /* */ C /* */ implements /* */ I"); \ No newline at end of file +verify.codeFix({ + description: "Change 'extends' to 'implements'.", + newRangeContent: "/* */ class /* */ C /* */ implements /* */ I", +}); diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts index 5f5ca93c28fc8..7f309a2296582 100644 --- a/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsAbstractModifier.ts @@ -5,4 +5,8 @@ //// [|abstract class A extends I1 implements I2|] { } -verify.rangeAfterCodeFix("abstract class A implements I1, I2"); \ No newline at end of file +verify.codeFix({ + description: "Change 'extends' to 'implements'.", + // TODO: GH#18794 + newRangeContent: "abstract class A implements I1 , I2", +}); diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts index 869bd1a5dc0a0..2cca0b277fd8f 100644 --- a/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsTypeParams.ts @@ -3,4 +3,7 @@ ////interface I { x: X} ////[|class C extends I|]{} -verify.rangeAfterCodeFix("class C implements I"); \ No newline at end of file +verify.codeFix({ + description: "Change 'extends' to 'implements'.", + newRangeContent: "class C implements I", +}); diff --git a/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts b/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts index 9671f41def335..e031251ac1b42 100644 --- a/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts +++ b/tests/cases/fourslash/codeFixChangeExtendsToImplementsWithDecorator.ts @@ -10,4 +10,8 @@ //// @sealed //// [|class A extends I1 implements I2 { }|] -verify.rangeAfterCodeFix("class A implements I1, I2 { }"); \ No newline at end of file +verify.codeFix({ + description: "Change 'extends' to 'implements'.", + // TODO: GH#18794 + newRangeContent: "class A implements I1 , I2 { }", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts index 93107ef669bb8..1a4e967df45bc 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax1.ts @@ -1,4 +1,7 @@ /// //// var x: [|?|] = 12; -verify.rangeAfterCodeFix("any"); +verify.codeFix({ + description: "Change '?' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax10.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax10.ts index 3e6754588fd70..12ddb66c6fd51 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax10.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax10.ts @@ -2,4 +2,10 @@ /// //// function f(x: [|number?|]) { //// } -verify.rangeAfterCodeFix("number | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); + +verify.codeFix({ + description: "Change 'number?' to 'number | null'.", + errorCode: 8020, + index: 0, + newRangeContent: "number | null", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax11.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax11.ts index 7ac80125775a9..8edcbb35da297 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax11.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax11.ts @@ -2,4 +2,10 @@ /// //// var f = function f(x: [|string?|]) { //// } -verify.rangeAfterCodeFix("string | null | undefined", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 1); + +verify.codeFix({ + description: "Change 'string?' to 'string | null | undefined'.", + errorCode: 8020, + index: 1, + newRangeContent: "string | null | undefined", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax12.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax12.ts index 37eb5df41ee8a..a2221897aa877 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax12.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax12.ts @@ -3,4 +3,10 @@ ////class C { //// p: [|*|] ////} -verify.rangeAfterCodeFix("any", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); + +verify.codeFix({ + description: "Change '*' to 'any'.", + errorCode: 8020, + index: 0, + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax13.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax13.ts index 5b374b508f14c..65fef47feda11 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax13.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax13.ts @@ -3,4 +3,10 @@ ////class C { //// p: [|*|] = 12 ////} -verify.rangeAfterCodeFix("any", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); + +verify.codeFix({ + description: "Change '*' to 'any'.", + errorCode: 8020, + index: 0, + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax14.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax14.ts index 69478fc3abca0..71f21dd83013c 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax14.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax14.ts @@ -2,4 +2,9 @@ /// //// var x = 12 as [|number?|]; -verify.rangeAfterCodeFix("number | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); +verify.codeFix({ + description: "Change 'number?' to 'number | null'.", + errorCode: 8020, + index: 0, + newRangeContent: "number | null", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax15.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax15.ts index 9482830c19dfc..b0e8c069e1e05 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax15.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax15.ts @@ -2,4 +2,9 @@ //// var f = <[|function(number?): number|]>(x => x); // note: without --strict, number? --> number, not number | null -verify.rangeAfterCodeFix("(arg0: number) => number", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); +verify.codeFix({ + description: "Change 'function(number?): number' to '(arg0: number) => number'.", + errorCode: 8020, + index: 0, + newRangeContent: "(arg0: number) => number", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax16.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax16.ts index 111aec1dce77f..264e490d961cc 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax16.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax16.ts @@ -1,4 +1,7 @@ /// //// var f: { [K in keyof number]: [|*|] }; -verify.rangeAfterCodeFix("any"); +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax17.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax17.ts index 6a3ce2ed3df5b..63973222a8acb 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax17.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax17.ts @@ -1,3 +1,7 @@ /// //// declare function index(ix: number): [|*|]; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax18.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax18.ts index 30a3815516a70..31b04bef0f603 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax18.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax18.ts @@ -1,3 +1,7 @@ /// //// var index: { (ix: number): [|?|] }; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '?' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax19.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax19.ts index e6344881227cb..d254cf6d8dd59 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax19.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax19.ts @@ -1,3 +1,7 @@ /// //// var index: { new (ix: number): [|?|] }; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '?' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax2.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax2.ts index 333b108538fd5..d2dc0986a59b1 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax2.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax2.ts @@ -1,4 +1,7 @@ /// //// var x: [|*|] = 12; -verify.rangeAfterCodeFix("any"); +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax20.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax20.ts index dc15373084175..32cfe73fd4acf 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax20.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax20.ts @@ -1,3 +1,7 @@ /// //// var index = { get p(): [|*|] { return 12 } }; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax21.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax21.ts index 442414e457756..efb53d53009e3 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax21.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax21.ts @@ -1,3 +1,7 @@ /// //// var index = { set p(x: [|*|]) { } }; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax22.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax22.ts index c575f1ca7ced4..06ff23c3cf589 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax22.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax22.ts @@ -1,3 +1,7 @@ /// //// var index: { [s: string]: [|*|] }; -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax23.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax23.ts index 7ab70e18ee7eb..29a49ff641c69 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax23.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax23.ts @@ -3,4 +3,8 @@ //// m(): [|*|] { //// } ////} -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax24.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax24.ts index 7ea2d1f6fafc1..6c9a840a373ab 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax24.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax24.ts @@ -2,4 +2,8 @@ ////declare class C { //// m(): [|*|]; ////} -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax25.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax25.ts index 6486a70417ef5..74a7ea9fa1813 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax25.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax25.ts @@ -2,4 +2,8 @@ ////declare class C { //// p: [|*|]; ////} -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax26.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax26.ts index dc31f1dfffdaa..4287539173a73 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax26.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax26.ts @@ -2,4 +2,8 @@ ////class C { //// p: [|*|] = 12; ////} -verify.rangeAfterCodeFix("any"); + +verify.codeFix({ + description: "Change '*' to 'any'.", + newRangeContent: "any", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax27.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax27.ts index a259b2dd719a1..998a9ebd28aa9 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax27.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax27.ts @@ -1,4 +1,10 @@ // @strict: true /// ////type T = [|...number?|]; -verify.rangeAfterCodeFix("number[] | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); + +verify.codeFix({ + description: "Change '...number?' to 'number[] | null'.", + errorCode: 8020, + index: 0, + newRangeContent: "number[] | null", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax3.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax3.ts index f3b02cb84f13c..2c804edb615b0 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax3.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax3.ts @@ -1,4 +1,7 @@ /// //// var x: [|......number[][]|] = 12; -verify.rangeAfterCodeFix("number[][][][]"); +verify.codeFix({ + description: "Change '......number[][]' to 'number[][][][]'.", + newRangeContent: "number[][][][]", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax4.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax4.ts index e9522331d389e..f2df4abfd3388 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax4.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax4.ts @@ -1,4 +1,7 @@ /// //// var x: [|Array.|] = 12; -verify.rangeAfterCodeFix("number[]"); +verify.codeFix({ + description: "Change 'Array.' to 'number[]'.", + newRangeContent: "number[]", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax5.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax5.ts index 6f46f3082e13c..39cca325a4cf6 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax5.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax5.ts @@ -2,4 +2,9 @@ /// //// var x: [|?number|] = 12; -verify.rangeAfterCodeFix("number | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0); +verify.codeFix({ + description: "Change '?number' to 'number | null'.", + errorCode: 8020, + index: 0, + newRangeContent: "number | null", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax6.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax6.ts index 8af9f09d99dd5..da692d723bb36 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax6.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax6.ts @@ -2,4 +2,8 @@ /// //// var x: [|number?|] = 12; -verify.rangeAfterCodeFix("number | null | undefined", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 1); +verify.codeFix({ + description: "Change 'number?' to 'number | null | undefined'.", + index: 1, + newRangeContent: "number | null | undefined", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax7.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax7.ts index c80d08b3bac58..1d557896fe9a4 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax7.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax7.ts @@ -1,4 +1,7 @@ /// //// var x: [|!number|] = 12; -verify.rangeAfterCodeFix("number"); +verify.codeFix({ + description: "Change '!number' to 'number'.", + newRangeContent: "number", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax8.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax8.ts index 0fa7ddf229cdb..c35badc88cf30 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax8.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax8.ts @@ -1,4 +1,7 @@ /// //// var x: [|function(this: number, number): string|] = 12; -verify.rangeAfterCodeFix("(this: number, arg1: number) => string"); +verify.codeFix({ + description: "Change 'function(this: number, number): string' to '(this: number, arg1: number) => string'.", + newRangeContent: "(this: number, arg1: number) => string", +}); diff --git a/tests/cases/fourslash/codeFixChangeJSDocSyntax9.ts b/tests/cases/fourslash/codeFixChangeJSDocSyntax9.ts index 061ded158ead8..6ce049b6a42d3 100644 --- a/tests/cases/fourslash/codeFixChangeJSDocSyntax9.ts +++ b/tests/cases/fourslash/codeFixChangeJSDocSyntax9.ts @@ -1,4 +1,7 @@ /// //// var x: [|function(new: number)|] = 12; -verify.rangeAfterCodeFix("new () => number"); +verify.codeFix({ + description: "Change 'function(new: number)' to 'new () => number'.", + newRangeContent: "new () => number", +}); diff --git a/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts b/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts index 2568111fb90d8..b582c5e89602e 100644 --- a/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts +++ b/tests/cases/fourslash/codeFixClassExprClassImplementClassFunctionVoidInferred.ts @@ -1,13 +1,16 @@ /// -//// class A { -//// f() {} -//// } +////class A { +//// f() {} +////} //// -//// let B = class implements A {[| |]} +////let B = class implements A {[| |]} -verify.rangeAfterCodeFix(` -f(): void{ - throw new Error("Method not implemented."); -} -`); +verify.codeFix({ + description: "Implement interface 'A'.", + // TODO: GH#18795 + newRangeContent: `f(): void {\r + throw new Error("Method not implemented.");\r +}\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts b/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts index a7690b4f5bf18..198cb9ea673fa 100644 --- a/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts +++ b/tests/cases/fourslash/codeFixClassExprExtendsAbstractExpressionWithTypeArgs.ts @@ -1,14 +1,17 @@ /// -//// function foo(a: T) { -//// abstract class C { -//// abstract a: T | U; -//// } -//// return C; -//// } +////function foo(a: T) { +//// abstract class C { +//// abstract a: T | U; +//// } +//// return C; +////} //// -//// let B = class extends foo("s") {[| |]} +////let B = class extends foo("s") {[| |]} -verify.rangeAfterCodeFix(` -a: string | number; -`); +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `a: string | number;\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts b/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts index 5796bea6fb485..ed574348b9f43 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractExpressionWithTypeArgs.ts @@ -1,14 +1,17 @@ /// -//// function foo(a: T) { -//// abstract class C { -//// abstract a: T | U; -//// } -//// return C; -//// } +////function foo(a: T) { +//// abstract class C { +//// abstract a: T | U; +//// } +//// return C; +////} //// -//// class B extends foo("s") {[| |]} +////class B extends foo("s") {[| |]} -verify.rangeAfterCodeFix(` -a: string | number; -`); \ No newline at end of file +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `a: string | number;\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts index bc437c93bcdfc..3522b1d39da17 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractGetterSetter.ts @@ -1,31 +1,34 @@ /// -//// abstract class A { -//// private _a: string; +////abstract class A { +//// private _a: string; //// -//// abstract get a(): number | string; -//// abstract get b(): this; -//// abstract get c(): A; +//// abstract get a(): number | string; +//// abstract get b(): this; +//// abstract get c(): A; //// -//// abstract set d(arg: number | string); -//// abstract set e(arg: this); -//// abstract set f(arg: A); +//// abstract set d(arg: number | string); +//// abstract set e(arg: this); +//// abstract set f(arg: A); //// -//// abstract get g(): string; -//// abstract set g(newName: string); -//// } -//// -//// // Don't need to add anything in this case. -//// abstract class B extends A {} -//// -//// class C extends A {[| |]} +//// abstract get g(): string; +//// abstract set g(newName: string); +////} +//// +////// Don't need to add anything in this case. +////abstract class B extends A {} +//// +////class C extends A {[| |]} -verify.rangeAfterCodeFix(` - a: string | number; - b: this; - c: A; - d: string | number; - e: this; - f: A; - g: string; -`); +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `a: string | number;\r +b: this;\r +c: A;\r +d: string | number;\r +e: this;\r +f: A;\r +g: string;\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts index 7e51e2216dc77..de9500552ab4c 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethod.ts @@ -1,24 +1,27 @@ /// -//// abstract class A { +////abstract class A { //// abstract f(a: number, b: string): boolean; //// abstract f(a: number, b: string): this; //// abstract f(a: string, b: number): Function; //// abstract f(a: string): Function; //// abstract foo(): number; -//// } +////} //// -//// class C extends A {[| |]} +////class C extends A {[| |]} -verify.rangeAfterCodeFix(` - f(a: number, b: string): boolean; - f(a: number, b: string): this; - f(a: string, b: number): Function; - f(a: string): Function; - f(a: any, b?: any) { - throw new Error("Method not implemented."); - } - foo(): number { - throw new Error("Method not implemented."); - } -`); +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `f(a: number, b: string): boolean;\r +f(a: number, b: string): this;\r +f(a: string, b: number): Function;\r +f(a: string): Function;\r +f(a: any, b?: any) {\r + throw new Error("Method not implemented.");\r +}\r +foo(): number {\r + throw new Error("Method not implemented.");\r +}\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts index a462ac98121cd..e33338b45a99d 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodThis.ts @@ -1,13 +1,16 @@ /// -//// abstract class A { +////abstract class A { //// abstract f(): this; -//// } +////} //// -//// class C extends A {[| |]} +////class C extends A {[| |]} -verify.rangeAfterCodeFix(` - f(): this { - throw new Error("Method not implemented."); - } -`); +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `f(): this {\r + throw new Error("Method not implemented.");\r +}\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts index c1a55e8803464..395d9348b7928 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateNumber.ts @@ -1,12 +1,16 @@ /// -//// abstract class A { +////abstract class A { //// abstract f(x: T): T; -//// } +////} //// -//// class C extends A {[| |]} +////class C extends A {[| |]} -verify.rangeAfterCodeFix(`f(x: number): number{ - throw new Error("Method not implemented."); -} -`); \ No newline at end of file +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `f(x: number): number {\r + throw new Error("Method not implemented.");\r +}\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts index c2ec5ff8035fb..408406a9efe8f 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethodTypeParamsInstantiateU.ts @@ -1,12 +1,16 @@ /// -//// abstract class A { +////abstract class A { //// abstract f(x: T): T; -//// } +////} //// -//// class C extends A {[| |]} +////class C extends A {[| |]} -verify.rangeAfterCodeFix(`f(x: U): U{ - throw new Error("Method not implemented."); -} -`); \ No newline at end of file +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `f(x: U): U {\r + throw new Error("Method not implemented.");\r +}\r + ` +}); diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts index 701903d67706f..fbdb13f4f2c91 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractProperty.ts @@ -1,15 +1,18 @@ /// -//// abstract class A { +////abstract class A { //// abstract x: number; //// abstract y: this; //// abstract z: A; -//// } +////} //// -//// class C extends A {[| |]} +////class C extends A {[| |]} -verify.rangeAfterCodeFix(` - x: number; - y: this; - z: A; -`); +verify.codeFix({ + description: "Implement inherited abstract class.", + // TODO: GH#18795 + newRangeContent: `x: number;\r +y: this;\r +z: A;\r + ` +}); diff --git a/tests/cases/fourslash/unusedMethodInClass1.ts b/tests/cases/fourslash/unusedMethodInClass1.ts index a5e3789c8af7f..175d95e249021 100644 --- a/tests/cases/fourslash/unusedMethodInClass1.ts +++ b/tests/cases/fourslash/unusedMethodInClass1.ts @@ -1,11 +1,12 @@ /// // @noUnusedLocals: true -////[| class greeter { +////class greeter { //// private function1() { //// } -////} |] +////} -verify.rangeAfterCodeFix(` -class greeter { -}`); +verify.codeFix({ + description: `Remove declaration for: 'function1'.`, + newFileContent: "class greeter {\n}", +}); diff --git a/tests/cases/fourslash/unusedMethodInClass2.ts b/tests/cases/fourslash/unusedMethodInClass2.ts index cce621236d4df..884f7ecce4e83 100644 --- a/tests/cases/fourslash/unusedMethodInClass2.ts +++ b/tests/cases/fourslash/unusedMethodInClass2.ts @@ -1,15 +1,17 @@ /// // @noUnusedLocals: true -//// [| class greeter { +////class greeter { //// public function2() { //// } //// private function1() { //// } -////} |] +////} -verify.rangeAfterCodeFix(` -class greeter { +verify.codeFix({ + description: `Remove declaration for: 'function1'.`, + newFileContent: `class greeter { public function2() { } -}`); +}`, +}); diff --git a/tests/cases/fourslash/unusedMethodInClass3.ts b/tests/cases/fourslash/unusedMethodInClass3.ts index ccf98c4bbc52b..f76a1acde0924 100644 --- a/tests/cases/fourslash/unusedMethodInClass3.ts +++ b/tests/cases/fourslash/unusedMethodInClass3.ts @@ -1,11 +1,12 @@ /// // @noUnusedLocals: true -////[|class greeter { +////class greeter { //// private function1 = function() { //// } -////} |] +////} -verify.rangeAfterCodeFix(` -class greeter { -}`); +verify.codeFix({ + description: `Remove declaration for: 'function1'.`, + newFileContent: "class greeter {\n}", +}); diff --git a/tests/cases/fourslash/unusedMethodInClass4.ts b/tests/cases/fourslash/unusedMethodInClass4.ts index 962b80f5bc142..9f882a3b76eea 100644 --- a/tests/cases/fourslash/unusedMethodInClass4.ts +++ b/tests/cases/fourslash/unusedMethodInClass4.ts @@ -8,5 +8,9 @@ //// } |] ////} -verify.rangeAfterCodeFix(`public function2(){ -}`); +verify.codeFix({ + description: `Remove declaration for: 'function1'.`, + newRangeContent: `public function2(){ + } +`, +}); diff --git a/tests/cases/fourslash/unusedMethodInClass5.ts b/tests/cases/fourslash/unusedMethodInClass5.ts index 806e619817f89..c53a31b5d36e3 100644 --- a/tests/cases/fourslash/unusedMethodInClass5.ts +++ b/tests/cases/fourslash/unusedMethodInClass5.ts @@ -1,8 +1,11 @@ /// // @noUnusedLocals: true -//// [|class C { -//// private ["string"] (){} -//// }|] +////class C { +//// private ["string"] (){} +////} -verify.rangeAfterCodeFix("class C { }"); \ No newline at end of file +verify.codeFix({ + description: `Remove declaration for: '"string"'.`, + newFileContent: "class C {\n}", +}); diff --git a/tests/cases/fourslash/unusedMethodInClass6.ts b/tests/cases/fourslash/unusedMethodInClass6.ts index d223b3d6857ec..eef00d1cdd03a 100644 --- a/tests/cases/fourslash/unusedMethodInClass6.ts +++ b/tests/cases/fourslash/unusedMethodInClass6.ts @@ -1,8 +1,11 @@ /// // @noUnusedLocals: true -//// [|class C { -//// private "string" (){} -//// }|] +////class C { +//// private "string" (){} +////} -verify.rangeAfterCodeFix("class C { }"); \ No newline at end of file +verify.codeFix({ + description: `Remove declaration for: '"string"'.`, + newFileContent: "class C {\n}", +}); diff --git a/tests/cases/fourslash/unusedNamespaceInNamespace.ts b/tests/cases/fourslash/unusedNamespaceInNamespace.ts index 802336454c6f8..4391a6a158c43 100644 --- a/tests/cases/fourslash/unusedNamespaceInNamespace.ts +++ b/tests/cases/fourslash/unusedNamespaceInNamespace.ts @@ -1,13 +1,13 @@ /// // @noUnusedLocals: true -//// [|namespace A { +////namespace A { //// namespace B { -//// } -//// }|] - -verify.rangeAfterCodeFix(` -namespace A { -} -`); +//// } +////} +verify.codeFix({ + description: "Remove declaration for: 'B'.", + newFileContent: `namespace A { +}`, +}); diff --git a/tests/cases/fourslash/unusedParameterInConstructor1.ts b/tests/cases/fourslash/unusedParameterInConstructor1.ts index 33fe34c7e613c..46a8c1f3b5244 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor1.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor1.ts @@ -5,4 +5,8 @@ //// [|constructor(private p1: string, public p2: boolean, public p3: any, p5)|] { p5; } //// } -verify.rangeAfterCodeFix("constructor(public p2: boolean, public p3: any, p5)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'p1'.", + index: 0, + newRangeContent: "constructor(public p2: boolean, public p3: any, p5)", +}); diff --git a/tests/cases/fourslash/unusedParameterInConstructor1AddUnderscore.ts b/tests/cases/fourslash/unusedParameterInConstructor1AddUnderscore.ts index 31882978951ac..634561a5c65f5 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor1AddUnderscore.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor1AddUnderscore.ts @@ -5,4 +5,8 @@ //// [|constructor(private p1: string, public p2: boolean, public p3: any, p5) |] { p5; } //// } -verify.rangeAfterCodeFix("constructor(private _p1: string, public p2: boolean, public p3: any, p5)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); \ No newline at end of file +verify.codeFix({ + description: "Prefix 'p1' with an underscore.", + index: 1, + newRangeContent: "constructor(private _p1: string, public p2: boolean, public p3: any, p5)", +}); diff --git a/tests/cases/fourslash/unusedParameterInConstructor2.ts b/tests/cases/fourslash/unusedParameterInConstructor2.ts index 71595a9c81cbb..b8208bb535958 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor2.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor2.ts @@ -5,4 +5,8 @@ //// [|constructor(public p1: string, private p2: boolean, public p3: any, p5)|] { p5; } //// } -verify.rangeAfterCodeFix("constructor(public p1: string, public p3: any, p5)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'p2'.", + index: 0, + newRangeContent: "constructor(public p1: string, public p3: any, p5)", +}); diff --git a/tests/cases/fourslash/unusedParameterInConstructor3.ts b/tests/cases/fourslash/unusedParameterInConstructor3.ts index 3da0e85407f92..c36f24595a777 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor3.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor3.ts @@ -5,4 +5,8 @@ //// [|constructor(public p1: string, public p2: boolean, private p3: any, p5)|] { p5; } //// } -verify.rangeAfterCodeFix("constructor(public p1: string, public p2: boolean, p5)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'p3'.", + index: 0, + newRangeContent: "constructor(public p1: string, public p2: boolean, p5)", +}); diff --git a/tests/cases/fourslash/unusedParameterInConstructor4.ts b/tests/cases/fourslash/unusedParameterInConstructor4.ts index 860a7befa9b6f..99e98d64cdac5 100644 --- a/tests/cases/fourslash/unusedParameterInConstructor4.ts +++ b/tests/cases/fourslash/unusedParameterInConstructor4.ts @@ -5,4 +5,8 @@ //// [|constructor(private readonly p2: boolean, p5)|] { p5; } //// } -verify.rangeAfterCodeFix("constructor(p5)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'p2'.", + index: 0, + newRangeContent: "constructor(p5)", +}); diff --git a/tests/cases/fourslash/unusedParameterInFunction1.ts b/tests/cases/fourslash/unusedParameterInFunction1.ts index bc6f081ecaa59..3f979f787668f 100644 --- a/tests/cases/fourslash/unusedParameterInFunction1.ts +++ b/tests/cases/fourslash/unusedParameterInFunction1.ts @@ -4,4 +4,8 @@ ////function [|greeter( x)|] { ////} -verify.rangeAfterCodeFix("greeter()", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + index: 0, + newRangeContent: "greeter()", +}); diff --git a/tests/cases/fourslash/unusedParameterInFunction1AddUnderscore.ts b/tests/cases/fourslash/unusedParameterInFunction1AddUnderscore.ts index 137625869c8bc..c248c5e1a94cc 100644 --- a/tests/cases/fourslash/unusedParameterInFunction1AddUnderscore.ts +++ b/tests/cases/fourslash/unusedParameterInFunction1AddUnderscore.ts @@ -4,4 +4,8 @@ ////function [|greeter( x) |] { ////} -verify.rangeAfterCodeFix("greeter( _x)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); +verify.codeFix({ + description: "Prefix 'x' with an underscore.", + index: 1, + newRangeContent: "greeter( _x)", +}); diff --git a/tests/cases/fourslash/unusedParameterInFunction2.ts b/tests/cases/fourslash/unusedParameterInFunction2.ts index 6d1a772b0a81d..74d95c9922177 100644 --- a/tests/cases/fourslash/unusedParameterInFunction2.ts +++ b/tests/cases/fourslash/unusedParameterInFunction2.ts @@ -5,4 +5,8 @@ //// use(x); ////} -verify.rangeAfterCodeFix("greeter(x)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'y'.", + index: 0, + newRangeContent: "greeter(x)", +}); diff --git a/tests/cases/fourslash/unusedParameterInFunction3.ts b/tests/cases/fourslash/unusedParameterInFunction3.ts index dcbe53163db59..30dc2a940609b 100644 --- a/tests/cases/fourslash/unusedParameterInFunction3.ts +++ b/tests/cases/fourslash/unusedParameterInFunction3.ts @@ -5,4 +5,8 @@ //// y++; ////} -verify.rangeAfterCodeFix("greeter(y)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'x'.", + index: 0, + newRangeContent: "greeter(y)", +}); diff --git a/tests/cases/fourslash/unusedParameterInFunction4.ts b/tests/cases/fourslash/unusedParameterInFunction4.ts index e3ee25853840c..87b5880ba70f4 100644 --- a/tests/cases/fourslash/unusedParameterInFunction4.ts +++ b/tests/cases/fourslash/unusedParameterInFunction4.ts @@ -5,4 +5,8 @@ //// use(x, z); ////} -verify.rangeAfterCodeFix("function greeter(x,z)", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'y'.", + index: 0, + newRangeContent: "function greeter(x,z) ", +}); diff --git a/tests/cases/fourslash/unusedParameterInLambda1.ts b/tests/cases/fourslash/unusedParameterInLambda1.ts index a5f735c701654..325502ebb6d9e 100644 --- a/tests/cases/fourslash/unusedParameterInLambda1.ts +++ b/tests/cases/fourslash/unusedParameterInLambda1.ts @@ -6,4 +6,8 @@ //// [|return (x:number) => {}|] //// } -verify.rangeAfterCodeFix("return () => {}", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + index: 0, + newRangeContent: "return () => {}", +}); diff --git a/tests/cases/fourslash/unusedParameterInLambda1AddUnderscore.ts b/tests/cases/fourslash/unusedParameterInLambda1AddUnderscore.ts index 916c32d82ebf2..1b05c66dd2fb5 100644 --- a/tests/cases/fourslash/unusedParameterInLambda1AddUnderscore.ts +++ b/tests/cases/fourslash/unusedParameterInLambda1AddUnderscore.ts @@ -6,4 +6,8 @@ //// [|return (x:number) => {} |] //// } -verify.rangeAfterCodeFix("return (_x:number) => {}", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); +verify.codeFix({ + description: "Prefix 'x' with an underscore.", + index: 1, + newRangeContent: "return (_x:number) => {}", +}); diff --git a/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts b/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts index 2314ebbe447e9..13c87f6afd6a1 100644 --- a/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts +++ b/tests/cases/fourslash/unusedTypeAliasInNamespace1.ts @@ -1,11 +1,14 @@ /// // @noUnusedLocals: true -//// [| namespace greeter { -//// type hw = "Hello" |"world"; -//// export type nw = "No" | "Way"; -//// } |] +////namespace greeter { +//// type hw = "Hello" |"world"; +//// export type nw = "No" | "Way"; +////} -verify.rangeAfterCodeFix(`namespace greeter { +verify.codeFix({ + description: "Remove declaration for: 'hw'.", + newFileContent: `namespace greeter { export type nw = "No" | "Way"; -}`); +}`, +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInClass1.ts b/tests/cases/fourslash/unusedTypeParametersInClass1.ts index 322921ab47133..6574362511f4a 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass1.ts @@ -4,4 +4,7 @@ ////[|class greeter |] { ////} -verify.rangeAfterCodeFix("class greeter"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "class greeter ", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInClass2.ts b/tests/cases/fourslash/unusedTypeParametersInClass2.ts index feaf9d3a14b77..3cb984a11ecb8 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass2.ts @@ -5,4 +5,7 @@ //// public a: X; ////} -verify.rangeAfterCodeFix("class greeter"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'Y'.", + newRangeContent: "class greeter ", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInClass3.ts b/tests/cases/fourslash/unusedTypeParametersInClass3.ts index b1151265fe351..13ebc352cb00c 100644 --- a/tests/cases/fourslash/unusedTypeParametersInClass3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInClass3.ts @@ -6,4 +6,7 @@ //// public b: Z; ////} -verify.rangeAfterCodeFix("class greeter"); +verify.codeFix({ + description: "Remove declaration for: 'Y'.", + newRangeContent: "class greeter ", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction1.ts b/tests/cases/fourslash/unusedTypeParametersInFunction1.ts index a11156badaaa9..b7289fc1e0a10 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction1.ts @@ -3,4 +3,7 @@ // @noUnusedLocals: true //// [|function f1() {}|] -verify.rangeAfterCodeFix("function f1() {}"); +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "function f1() {}", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction2.ts b/tests/cases/fourslash/unusedTypeParametersInFunction2.ts index a011f093dab32..e2851b346054a 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction2.ts @@ -3,4 +3,7 @@ // @noUnusedLocals: true //// [|function f1(a: X) {a}|] -verify.rangeAfterCodeFix("function f1(a: X) {a}"); +verify.codeFix({ + description: "Remove declaration for: 'Y'.", + newRangeContent: "function f1(a: X) {a}", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInFunction3.ts b/tests/cases/fourslash/unusedTypeParametersInFunction3.ts index 6dc56ccc7cbfd..4be2dc5feb336 100644 --- a/tests/cases/fourslash/unusedTypeParametersInFunction3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInFunction3.ts @@ -3,4 +3,7 @@ // @noUnusedLocals: true //// [|function f1(a: X) {a;var b:Z;b}|] -verify.rangeAfterCodeFix("function f1(a: X) {a;var b:Z;b}"); +verify.codeFix({ + description: "Remove declaration for: 'Y'.", + newRangeContent: "function f1(a: X) {a;var b:Z;b}", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInInterface1.ts b/tests/cases/fourslash/unusedTypeParametersInInterface1.ts index b5363b369be70..bc3a95d63b6a8 100644 --- a/tests/cases/fourslash/unusedTypeParametersInInterface1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInInterface1.ts @@ -4,4 +4,7 @@ // @noUnusedParameters: true //// [|interface I {}|] -verify.rangeAfterCodeFix("interface I {}"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "interface I {}", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda1.ts b/tests/cases/fourslash/unusedTypeParametersInLambda1.ts index 01c1ebd24f52d..3d7310d6ae6f8 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda1.ts @@ -6,4 +6,7 @@ //// [|return (x:number) => {x}|] //// } -verify.rangeAfterCodeFix("return (x:number) => {x}"); +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "return(x:number) => {x}", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda2.ts b/tests/cases/fourslash/unusedTypeParametersInLambda2.ts index e5a4acc31c53e..b2b89d3373ea4 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda2.ts @@ -6,4 +6,7 @@ //// [|new (a: T): void;|] //// } -verify.rangeAfterCodeFix("new (a: T): void;"); +verify.codeFix({ + description: "Remove declaration for: 'U'.", + newRangeContent: "new (a: T): void;", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda3.ts b/tests/cases/fourslash/unusedTypeParametersInLambda3.ts index e6d866dcb6aaa..1f994c4590598 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda3.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda3.ts @@ -7,4 +7,7 @@ //// [|new (a: T): A;|] //// } -verify.rangeAfterCodeFix("new (a: T): A;"); +verify.codeFix({ + description: "Remove declaration for: 'K'.", + newRangeContent: "new (a: T): A;", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInLambda4.ts b/tests/cases/fourslash/unusedTypeParametersInLambda4.ts index 04bd7c7e9becf..d5c01202d261f 100644 --- a/tests/cases/fourslash/unusedTypeParametersInLambda4.ts +++ b/tests/cases/fourslash/unusedTypeParametersInLambda4.ts @@ -6,4 +6,7 @@ //// } //// [|var y: new (a:T)=>void;|] -verify.rangeAfterCodeFix("var y: new (a:T)=>void;"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'U'.", + newRangeContent: "var y: new (a:T)=>void;", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInMethod1.ts b/tests/cases/fourslash/unusedTypeParametersInMethod1.ts index bc14952eca9b7..f4d036f54f493 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethod1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethod1.ts @@ -5,4 +5,7 @@ //// [|f1()|] {} //// } -verify.rangeAfterCodeFix("f1()"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "f1()", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInMethod2.ts b/tests/cases/fourslash/unusedTypeParametersInMethod2.ts index c12fd53f66b0b..25556ebc57dfa 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethod2.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethod2.ts @@ -5,4 +5,7 @@ //// [|f1(a: U)|] {a;} //// } -verify.rangeAfterCodeFix("f1(a: U)"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'T'.", + newRangeContent: "f1(a: U)", +}); diff --git a/tests/cases/fourslash/unusedTypeParametersInMethods1.ts b/tests/cases/fourslash/unusedTypeParametersInMethods1.ts index d0b170491f5e1..62f222464311e 100644 --- a/tests/cases/fourslash/unusedTypeParametersInMethods1.ts +++ b/tests/cases/fourslash/unusedTypeParametersInMethods1.ts @@ -5,4 +5,7 @@ //// [|public f1(a: X)|] { a; var b: Z; b } //// } -verify.rangeAfterCodeFix("public f1(a: X)"); +verify.codeFix({ + description: "Remove declaration for: 'Y'.", + newRangeContent: "public f1(a: X)", +}); diff --git a/tests/cases/fourslash/unusedVariableInBlocks.ts b/tests/cases/fourslash/unusedVariableInBlocks.ts index 2a33d0c4cf5c6..fe3c002916b43 100644 --- a/tests/cases/fourslash/unusedVariableInBlocks.ts +++ b/tests/cases/fourslash/unusedVariableInBlocks.ts @@ -1,15 +1,18 @@ /// // @noUnusedLocals: true -//// function f1 () { +////function f1 () { //// [|let x = 10; //// { //// let x = 11; //// } //// x;|] -//// } +////} -verify.rangeAfterCodeFix(`let x = 10; - { - } - x;`); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + newRangeContent: `let x = 10; + { + } + x;`, +}); diff --git a/tests/cases/fourslash/unusedVariableInClass1.ts b/tests/cases/fourslash/unusedVariableInClass1.ts index 8b0ca0db727db..e4cec171e8eda 100644 --- a/tests/cases/fourslash/unusedVariableInClass1.ts +++ b/tests/cases/fourslash/unusedVariableInClass1.ts @@ -5,4 +5,7 @@ //// [|private greeting: string;|] ////} -verify.rangeAfterCodeFix(""); +verify.codeFix({ + description: "Remove declaration for: 'greeting'.", + newRangeContent: "", +}); diff --git a/tests/cases/fourslash/unusedVariableInClass2.ts b/tests/cases/fourslash/unusedVariableInClass2.ts index 6503dd02872fe..1f632a43ce83b 100644 --- a/tests/cases/fourslash/unusedVariableInClass2.ts +++ b/tests/cases/fourslash/unusedVariableInClass2.ts @@ -6,4 +6,7 @@ //// private greeting: string;|] ////} -verify.rangeAfterCodeFix("public greeting1;"); +verify.codeFix({ + description: "Remove declaration for: 'greeting'.", + newRangeContent: "public greeting1;\n", +}); diff --git a/tests/cases/fourslash/unusedVariableInClass3.ts b/tests/cases/fourslash/unusedVariableInClass3.ts index 3ac306170a203..eec4e6bbe8fa9 100644 --- a/tests/cases/fourslash/unusedVariableInClass3.ts +++ b/tests/cases/fourslash/unusedVariableInClass3.ts @@ -5,4 +5,7 @@ //// private X = function() {}; ////|]} -verify.rangeAfterCodeFix(""); +verify.codeFix({ + description: "Remove declaration for: 'X'.", + newRangeContent: "\n", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop1FS.ts b/tests/cases/fourslash/unusedVariableInForLoop1FS.ts index 760d8487b3438..2a4feffd47450 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop1FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop1FS.ts @@ -7,5 +7,7 @@ //// } //// } -verify.rangeAfterCodeFix("for(; ;)"); - +verify.codeFix({ + description: "Remove declaration for: 'i'.", + newRangeContent: "for(; ;) ", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop2FS.ts b/tests/cases/fourslash/unusedVariableInForLoop2FS.ts index a16f21e8417a4..d913ae5ce94b2 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop2FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop2FS.ts @@ -7,4 +7,7 @@ //// } //// } -verify.rangeAfterCodeFix("for(var i = 0; ;i++)"); +verify.codeFix({ + description: "Remove declaration for: 'j'.", + newRangeContent: "for(var i = 0; ;i++)", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop3FS.ts b/tests/cases/fourslash/unusedVariableInForLoop3FS.ts index 07d13307ca794..6f3beae5c74d7 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop3FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop3FS.ts @@ -7,4 +7,7 @@ //// } //// } -verify.rangeAfterCodeFix("for(var i = 0, k=0; ;i++,k++)"); \ No newline at end of file +verify.codeFix({ + description: "Remove declaration for: 'j'.", + newRangeContent: "for(var i = 0, k=0; ;i++, k++)", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop4FS.ts b/tests/cases/fourslash/unusedVariableInForLoop4FS.ts index d54f8baaa3d5c..661012958d4f0 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop4FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop4FS.ts @@ -7,4 +7,7 @@ //// } //// } -verify.rangeAfterCodeFix("for(var j = 0, k=0; ;j++,k++)"); +verify.codeFix({ + description: "Remove declaration for: 'i'.", + newRangeContent: "for(var j= 0, k=0; ;j++, k++) ", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop5FSAddUnderscore.ts b/tests/cases/fourslash/unusedVariableInForLoop5FSAddUnderscore.ts index 2948bfab2075f..87783ff67fc0b 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop5FSAddUnderscore.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop5FSAddUnderscore.ts @@ -7,4 +7,7 @@ //// } //// } -verify.rangeAfterCodeFix(`for (const _elem in ["a", "b", "c"])`, /*includeWhiteSpace*/ true, /*errorCode*/ 0); +verify.codeFix({ + description: "Prefix 'elem' with an underscore.", + newRangeContent: 'for (const _elem in ["a", "b", "c"])' +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop6FS.ts b/tests/cases/fourslash/unusedVariableInForLoop6FS.ts index fa1948438bc09..9661514d43199 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop6FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop6FS.ts @@ -7,5 +7,8 @@ //// } //// } -verify.rangeAfterCodeFix("const {} of ", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); - +verify.codeFix({ + description: "Remove declaration for: 'elem'.", + index: 0, + newRangeContent: "const {} of", +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop6FSAddUnderscore.ts b/tests/cases/fourslash/unusedVariableInForLoop6FSAddUnderscore.ts index 4faa6893b7fa5..9f8c7b19f99d8 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop6FSAddUnderscore.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop6FSAddUnderscore.ts @@ -7,5 +7,9 @@ //// } //// } -verify.rangeAfterCodeFix("const _elem of", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); +verify.codeFix({ + description: "Prefix 'elem' with an underscore.", + index: 1, + newRangeContent: "const _elem of" +}); diff --git a/tests/cases/fourslash/unusedVariableInForLoop7FS.ts b/tests/cases/fourslash/unusedVariableInForLoop7FS.ts index 7f99863ba46ee..c42bf8bc97a28 100644 --- a/tests/cases/fourslash/unusedVariableInForLoop7FS.ts +++ b/tests/cases/fourslash/unusedVariableInForLoop7FS.ts @@ -9,8 +9,11 @@ ////}|] //// -verify.rangeAfterCodeFix(`{ +verify.codeFix({ + description: "Remove declaration for: 'x'.", + newRangeContent: `{ for (const elem of ["a", "b", "c"]) { elem; } -}`, /*includeWhiteSpace*/ true); +}` +}); diff --git a/tests/cases/fourslash/unusedVariableInModule1.ts b/tests/cases/fourslash/unusedVariableInModule1.ts index e9fe9515e6d8d..7a0a3ad86016a 100644 --- a/tests/cases/fourslash/unusedVariableInModule1.ts +++ b/tests/cases/fourslash/unusedVariableInModule1.ts @@ -6,4 +6,7 @@ //// [|var x: string; //// export var y: string;|] -verify.rangeAfterCodeFix("export var y: string;"); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + newRangeContent: "export var y: string;", +}); diff --git a/tests/cases/fourslash/unusedVariableInModule2.ts b/tests/cases/fourslash/unusedVariableInModule2.ts index ac6e7120d8bd9..e8a1ae762d4ef 100644 --- a/tests/cases/fourslash/unusedVariableInModule2.ts +++ b/tests/cases/fourslash/unusedVariableInModule2.ts @@ -7,4 +7,7 @@ //// z; //// export var y: string; -verify.rangeAfterCodeFix("var z: number;"); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + newRangeContent: "var z: number;", +}); diff --git a/tests/cases/fourslash/unusedVariableInModule3.ts b/tests/cases/fourslash/unusedVariableInModule3.ts index 0185b89e3a634..56b08f5499ef7 100644 --- a/tests/cases/fourslash/unusedVariableInModule3.ts +++ b/tests/cases/fourslash/unusedVariableInModule3.ts @@ -6,4 +6,7 @@ //// [|var x = function f1() {} //// export var y: string;|] -verify.rangeAfterCodeFix("export var y: string;"); +verify.codeFix({ + description: "Remove declaration for: 'x'.", + newRangeContent: "export var y: string;", +}); diff --git a/tests/cases/fourslash/unusedVariableInModule4.ts b/tests/cases/fourslash/unusedVariableInModule4.ts index 6d80d59c2ced2..71890893b9e7c 100644 --- a/tests/cases/fourslash/unusedVariableInModule4.ts +++ b/tests/cases/fourslash/unusedVariableInModule4.ts @@ -7,4 +7,8 @@ //// x; //// export var y: string; -verify.rangeAfterCodeFix(`var x = function f1() {}`, /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 0); +verify.codeFix({ + description: "Remove declaration for: 'm'.", + index: 0, + newRangeContent: `var x = function f1() {}`, +}); diff --git a/tests/cases/fourslash/unusedVariableInNamespace1.ts b/tests/cases/fourslash/unusedVariableInNamespace1.ts index c9f38473a5151..6dd14233683c2 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace1.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace1.ts @@ -5,4 +5,7 @@ //// [|let a = "dummy entry";|] ////} -verify.rangeAfterCodeFix(""); +verify.codeFix({ + description: "Remove declaration for: 'a'.", + newRangeContent: "", +}); diff --git a/tests/cases/fourslash/unusedVariableInNamespace2.ts b/tests/cases/fourslash/unusedVariableInNamespace2.ts index 61fc3ec137c0b..9bf546f6f53d7 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace2.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace2.ts @@ -8,4 +8,7 @@ //// } ////} -verify.rangeAfterCodeFix(`let a = "dummy entry", c = 0;`); +verify.codeFix({ + description: "Remove declaration for: 'b'.", + newRangeContent: 'let a = "dummy entry", c = 0;', +}); diff --git a/tests/cases/fourslash/unusedVariableInNamespace3.ts b/tests/cases/fourslash/unusedVariableInNamespace3.ts index 7d2f3d251f397..85e1889c3e1af 100644 --- a/tests/cases/fourslash/unusedVariableInNamespace3.ts +++ b/tests/cases/fourslash/unusedVariableInNamespace3.ts @@ -8,4 +8,7 @@ //// } ////} -verify.rangeAfterCodeFix(`let a = "dummy entry", b;`); +verify.codeFix({ + description: "Remove declaration for: 'c'.", + newRangeContent: 'let a = "dummy entry", b;', +}); From 9ece0cc956215ca1d82bf3f531a98ca44cdf5d66 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 10 Oct 2017 13:01:06 -0700 Subject: [PATCH 094/246] Move getSynthesizedDeepClone to services/utilities.ts --- src/compiler/factory.ts | 10 ---------- src/services/utilities.ts | 12 ++++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 7d703ffe06222..fe183c5e8060c 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -71,16 +71,6 @@ namespace ts { return clone; } - /** - * Creates a deep, memberwise clone of a node with no source map location. - */ - /* @internal */ - export function getSynthesizedDeepClone(node: T | undefined): T | undefined { - return node - ? getSynthesizedClone(visitEachChild(node, child => getSynthesizedDeepClone(child), nullTransformationContext)) - : undefined; - } - // Literals export function createLiteral(value: string): StringLiteral; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 6166ceea28ce1..c22b981b4ff15 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1334,4 +1334,16 @@ namespace ts { } return position; } + + /** + * Creates a deep, memberwise clone of a node with no source map location. + * + * WARNING: This is an expensive operation and is only intended to be used in refactorings + * and code fixes (because those are triggered by explicit user actions). + */ + export function getSynthesizedDeepClone(node: T | undefined): T | undefined { + return node + ? getSynthesizedClone(visitEachChild(node, child => getSynthesizedDeepClone(child), nullTransformationContext)) + : undefined; + } } From 18afd8a50d9d3430062b126c7404501c190376af Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 10 Oct 2017 13:08:57 -0700 Subject: [PATCH 095/246] Optimize getSynthesizedDeepClone --- src/services/utilities.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index c22b981b4ff15..5affb8a888736 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1342,8 +1342,24 @@ namespace ts { * and code fixes (because those are triggered by explicit user actions). */ export function getSynthesizedDeepClone(node: T | undefined): T | undefined { - return node - ? getSynthesizedClone(visitEachChild(node, child => getSynthesizedDeepClone(child), nullTransformationContext)) - : undefined; + if (node === undefined) { + return undefined; + } + + const visited = visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext); + if (visited === node) { + // This only happens for leaf nodes - internal nodes always see their children change. + return getSynthesizedClone(node); + } + + // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update + // the new node created by visitEachChild with the extra changes getSynthesizedClone + // would have made. + + visited.pos = -1; + visited.end = -1; + visited.parent = undefined; + + return visited; } } From 75fea4f5c401c808a77744923b3ae712a0f540a9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 10 Oct 2017 15:27:43 -0700 Subject: [PATCH 096/246] Update Authors for TS 2.6 --- .mailmap | 13 ++++++++++++- AUTHORS.md | 11 +++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index 7ae5cb1981823..98f004c58dc0d 100644 --- a/.mailmap +++ b/.mailmap @@ -276,4 +276,15 @@ Francois Wouts Jan Melcher Jan Melcher Matt Mitchell Maxwell Paul Brickner -Tycho Grouwstra \ No newline at end of file +Tycho Grouwstra +Adrian Leonhard +Alex Chugaev +Henry Mercer +Ivan Enderlin +Joe Calzaretta +Magnus Kulke +Stas Vilchik +Taras Mankovski +Thomas den Hollander +Vakhurin Sergey +Zeeshan Ahmed \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md index 4f94a67f7dd2e..c554a5887159b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -3,8 +3,10 @@ TypeScript is authored by: * Abubaker Bashir * Adam Freidin * Adi Dahiya +* Adrian Leonhard * Ahmad Farid * Akshar Patel +* Alex Chugaev * Alex Eagle * Alexander Kuvaev * Alexander Rusakov @@ -105,6 +107,7 @@ TypeScript is authored by: * Halasi Tamás * Harald Niesche * Hendrik Liebau +* Henry Mercer * Herrington Darkholme * Homa Wong * Iain Monro @@ -112,6 +115,7 @@ TypeScript is authored by: * Ika * Ingvar Stepanyan * Isiah Meadows +* Ivan Enderlin * Ivo Gabe de Wolff * Iwata Hidetaka * Jakub Młokosiewicz @@ -127,6 +131,7 @@ TypeScript is authored by: * Jeffrey Morlan * Jesse Schalken * Jiri Tobisek +* Joe Calzaretta * Joe Chung * Joel Day * Joey Wilson @@ -161,6 +166,7 @@ TypeScript is authored by: * Lucien Greathouse * Lukas Elmer * Magnus Hiie +* Magnus Kulke * Manish Giri * Marin Marinov * Marius Schulz @@ -232,13 +238,16 @@ TypeScript is authored by: * Soo Jae Hwang * Stan Thomas * Stanislav Sysoev +* Stas Vilchik * Steve Lucco * Sudheesh Singanamalla * Sébastien Arod * @T18970237136 * @t_ +* Taras Mankovski * Tarik Ozket * Tetsuharu Ohzeki +* Thomas den Hollander * Thomas Loubiou * Tien Hoanhtien * Tim Lancina @@ -253,6 +262,7 @@ TypeScript is authored by: * TruongSinh Tran-Nguyen * Tycho Grouwstra * Vadi Taslim +* Vakhurin Sergey * Vidar Tonaas Fauske * Viktor Zozulyak * Vilic Vane @@ -263,5 +273,6 @@ TypeScript is authored by: * York Yao * @yortus * Yuichi Nukiyama +* Zeeshan Ahmed * Zev Spitz * Zhengbo Li \ No newline at end of file From 611e0f7b4a86de98e96618296a1789a9c47e0223 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Oct 2017 15:37:05 -0700 Subject: [PATCH 097/246] Do not rely on parent pointers in the binder (#19083) --- src/compiler/binder.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4cacb5765db35..35a62a644d839 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -143,6 +143,15 @@ namespace ts { let subtreeTransformFlags: TransformFlags = TransformFlags.None; let skipTransformFlagAggregation: boolean; + /** + * Inside the binder, we may create a diagnostic for an as-yet unbound node (with potentially no parent pointers, implying no accessible source file) + * If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node) + * This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations. + */ + function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { + return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2); + } + function bindSourceFile(f: SourceFile, opts: CompilerOptions) { file = f; options = opts; From 249c2cbaf754164c3f6d0e7a03c53002575b4060 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Tue, 10 Oct 2017 15:39:59 -0700 Subject: [PATCH 098/246] Maintain Export Modifier when Refactoring to ES6 Class #18435 (#19070) --- .../refactors/convertFunctionToEs6Class.ts | 10 ++++++++-- ...nvertFunctionToEs6Class_exportModifier1.ts | 19 +++++++++++++++++++ ...nvertFunctionToEs6Class_exportModifier2.ts | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/convertFunctionToEs6Class_exportModifier1.ts create mode 100644 tests/cases/fourslash/convertFunctionToEs6Class_exportModifier2.ts diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index e4cd1a420832c..110f64d122043 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -243,7 +243,8 @@ namespace ts.refactor.convertFunctionToES6Class { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } - const cls = createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, node.name, + const modifiers = getExportModifierFromSource(precedingNode); + const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place return cls; @@ -255,10 +256,15 @@ namespace ts.refactor.convertFunctionToES6Class { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } - const cls = createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, node.name, + const modifiers = getExportModifierFromSource(node); + const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place return cls; } + + function getExportModifierFromSource(source: Node) { + return filter(source.modifiers, modifier => modifier.kind === SyntaxKind.ExportKeyword); + } } } \ No newline at end of file diff --git a/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier1.ts b/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier1.ts new file mode 100644 index 0000000000000..940a68a05b615 --- /dev/null +++ b/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier1.ts @@ -0,0 +1,19 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: test123.js +////export function /**/MyClass() { +////} +////MyClass.prototype.foo = function() { +////} + +verify.applicableRefactorAvailableAtMarker(""); +verify.fileAfterApplyingRefactorAtMarker("", +`export class MyClass { + constructor() { + } + foo() { + } +} +`, +'Convert to ES2015 class', 'convert'); diff --git a/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier2.ts b/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier2.ts new file mode 100644 index 0000000000000..fb1276d4f0352 --- /dev/null +++ b/tests/cases/fourslash/convertFunctionToEs6Class_exportModifier2.ts @@ -0,0 +1,19 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: test123.js +////export const /**/foo = function() { +////}; +////foo.prototype.instanceMethod = function() { +////}; + +verify.applicableRefactorAvailableAtMarker(""); +verify.fileAfterApplyingRefactorAtMarker("", +`export class foo { + constructor() { + } + instanceMethod() { + } +} +`, +'Convert to ES2015 class', 'convert'); From d086b637c53b391922b8f2671a37f9f062e46102 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Oct 2017 15:52:41 -0700 Subject: [PATCH 099/246] Remove `removeWhere` (#19082) --- src/compiler/core.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 45a4a04b6ab4d..fb5000a58bfc9 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -356,21 +356,6 @@ namespace ts { return array; } - export function removeWhere(array: T[], f: (x: T) => boolean): boolean { - let outIndex = 0; - for (const item of array) { - if (!f(item)) { - array[outIndex] = item; - outIndex++; - } - } - if (outIndex !== array.length) { - array.length = outIndex; - return true; - } - return false; - } - export function filterMutate(array: T[], f: (x: T, i: number, array: T[]) => boolean): void { let outIndex = 0; for (let i = 0; i < array.length; i++) { From 55bbcff348b49d063efe91e5d22e957ddb358076 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 16:36:09 -0700 Subject: [PATCH 100/246] Modify the changesAffectModuleResolution check --- src/compiler/watch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 1ab80e659f42d..4fc67c1cc8fc2 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -322,7 +322,7 @@ namespace ts { if (hasChangedCompilerOptions) { newLine = getNewLineCharacter(compilerOptions, system); - if (changesAffectModuleResolution(program && program.getCompilerOptions(), compilerOptions)) { + if (program && changesAffectModuleResolution(program.getCompilerOptions(), compilerOptions)) { resolutionCache.clear(); } } From cb326ed298599673a437ca719de032d8bed6501d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 16:39:13 -0700 Subject: [PATCH 101/246] Function to clear the per directory resolution --- src/compiler/resolutionCache.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 680ed98a84a4f..faf5fb2a9f4e7 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -107,7 +107,9 @@ namespace ts { return { startRecordingFilesWithChangedResolutions, finishRecordingFilesWithChangedResolutions, - startCachingPerDirectoryResolution, + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) + startCachingPerDirectoryResolution: clearPerDirectoryResolutions, finishCachingPerDirectoryResolution, resolveModuleNames, resolveTypeReferenceDirectives, @@ -143,8 +145,7 @@ namespace ts { allFilesHaveInvalidatedResolution = false; // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) - perDirectoryResolvedModuleNames.clear(); - perDirectoryResolvedTypeReferenceDirectives.clear(); + clearPerDirectoryResolutions(); } function startRecordingFilesWithChangedResolutions() { @@ -168,9 +169,7 @@ namespace ts { return path => collected && collected.has(path); } - function startCachingPerDirectoryResolution() { - // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update - // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) + function clearPerDirectoryResolutions() { perDirectoryResolvedModuleNames.clear(); perDirectoryResolvedTypeReferenceDirectives.clear(); } @@ -184,8 +183,7 @@ namespace ts { } }); - perDirectoryResolvedModuleNames.clear(); - perDirectoryResolvedTypeReferenceDirectives.clear(); + clearPerDirectoryResolutions(); } function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { From edf0a95e891da48b6206710e13c55eb018870ddd Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Oct 2017 16:41:54 -0700 Subject: [PATCH 102/246] Stop erroneous match of midfile sourceMappingUrl (#19084) --- src/harness/unittests/compileOnSave.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 1e765054eee9f..fdec5b192ee83 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -619,7 +619,7 @@ namespace ts.projectSystem { assert.isTrue(host.fileExists(expectedOutFileName)); const outFileContent = host.readFile(expectedOutFileName); verifyContentHasString(outFileContent, file1.content); - verifyContentHasString(outFileContent, `//# sourceMappingURL=${outFileName}.map`); + verifyContentHasString(outFileContent, `//# ${"sourceMappingURL"}=${outFileName}.map`); // Sometimes tools can sometimes see this line as a source mapping url comment, so we obfuscate it a little // Verify map file const expectedMapFileName = expectedOutFileName + ".map"; From e30a66d22f913b824427fd1323dfd82af20c8a76 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 17:08:47 -0700 Subject: [PATCH 103/246] Add utitlity for stringContains --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 8 ++++++-- src/compiler/declarationEmitter.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/moduleNameResolver.ts | 2 +- src/compiler/resolutionCache.ts | 3 +-- src/server/editorServices.ts | 2 +- src/server/session.ts | 2 +- src/server/typingsInstaller/nodeTypingsInstaller.ts | 2 +- src/services/pathCompletions.ts | 4 ++-- src/services/refactors/extractSymbol.ts | 2 +- src/services/services.ts | 2 +- 12 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d47a77a74401a..ab61d91ef1525 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14012,7 +14012,7 @@ namespace ts { */ function isUnhyphenatedJsxName(name: string | __String) { // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers - return (name as string).indexOf("-") < 0; + return !stringContains(name as string, "-"); } /** diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 45a4a04b6ab4d..442a262bbe236 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1663,7 +1663,7 @@ namespace ts { } export function isUrl(path: string) { - return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1; + return path && !isRootedDiskPath(path) && stringContains(path, "://"); } export function pathIsRelative(path: string): boolean { @@ -1932,8 +1932,12 @@ namespace ts { return expectedPos >= 0 && str.indexOf(suffix, expectedPos) === expectedPos; } + export function stringContains(str: string, substring: string): boolean { + return str.indexOf(substring) !== -1; + } + export function hasExtension(fileName: string): boolean { - return getBaseFileName(fileName).indexOf(".") >= 0; + return stringContains(getBaseFileName(fileName), "."); } export function fileExtensionIs(path: string, extension: string): boolean { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 3de2091502949..48b97b048e9cc 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -172,7 +172,7 @@ namespace ts { function hasInternalAnnotation(range: CommentRange) { const comment = currentText.substring(range.pos, range.end); - return comment.indexOf("@internal") >= 0; + return stringContains(comment, "@internal"); } function stripInternal(node: Node) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8083b3841c802..da6c0e0fca8f6 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1226,7 +1226,7 @@ namespace ts { // check if numeric literal is a decimal literal that was originally written with a dot const text = getLiteralTextOfNode(expression); return !expression.numericLiteralFlags - && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; + && !stringContains(text, tokenToString(SyntaxKind.DotToken)); } else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { // check if constant enum value is integer diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 560beb39557d4..ac83dd4131195 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1061,7 +1061,7 @@ namespace ts { export function getPackageNameFromAtTypesDirectory(mangledName: string): string { const withoutAtTypePrefix = removePrefix(mangledName, "@types/"); if (withoutAtTypePrefix !== mangledName) { - return withoutAtTypePrefix.indexOf(mangledScopedPackageSeparator) !== -1 ? + return stringContains(withoutAtTypePrefix, mangledScopedPackageSeparator) ? "@" + withoutAtTypePrefix.replace(mangledScopedPackageSeparator, ts.directorySeparator) : withoutAtTypePrefix; } diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 25545c0efbc80..3f3955b294f69 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -324,7 +324,7 @@ namespace ts { let dirPath = getDirectoryPath(failedLookupLocationPath); // If directory path contains node module, get the most parent node_modules directory for watching - while (dirPath.indexOf("/node_modules/") !== -1) { + while (stringContains(dirPath, "/node_modules/")) { dir = getDirectoryPath(dir); dirPath = getDirectoryPath(dirPath); } @@ -334,7 +334,6 @@ namespace ts { return { dir, dirPath }; } - // Use some ancestor of the root directory if (rootPath !== undefined) { while (!isInDirectoryPath(dirPath, rootPath)) { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2916fb60c5734..c683ff0080a88 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1205,7 +1205,7 @@ namespace ts.server { projectRootPath?: NormalizedPath) { let searchPath = asNormalizedPath(getDirectoryPath(info.fileName)); - while (!projectRootPath || searchPath.indexOf(projectRootPath) >= 0) { + while (!projectRootPath || stringContains(searchPath, projectRootPath)) { const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName); const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); let result = action(tsconfigFileName, combinePaths(canonicalSearchPath, "tsconfig.json")); diff --git a/src/server/session.ts b/src/server/session.ts index 57dac7ec799a0..df9c77b9005ea 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1608,7 +1608,7 @@ namespace ts.server { } // No need to analyze lib.d.ts - const fileNamesInProject = fileNames.filter(value => value.indexOf("lib.d.ts") < 0); + const fileNamesInProject = fileNames.filter(value => !stringContains(value, "lib.d.ts")); if (fileNamesInProject.length === 0) { return; } diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 6a31a114d23f3..f5d9b866376a0 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -88,7 +88,7 @@ namespace ts.server.typingsInstaller { this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0]); // If the NPM path contains spaces and isn't wrapped in quotes, do so. - if (this.npmPath.indexOf(" ") !== -1 && this.npmPath[0] !== `"`) { + if (stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) { this.npmPath = `"${this.npmPath}"`; } if (this.log.isEnabled()) { diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index c41ed798b1d27..e3bf9deac8932 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -195,7 +195,7 @@ namespace ts.Completions.PathCompletions { const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix); const normalizedPrefixBase = getBaseFileName(normalizedPrefix); - const fragmentHasPath = fragment.indexOf(directorySeparator) !== -1; + const fragmentHasPath = stringContains(fragment, directorySeparator); // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory; @@ -235,7 +235,7 @@ namespace ts.Completions.PathCompletions { function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] { // Check If this is a nested module - const isNestedModule = fragment.indexOf(directorySeparator) !== -1; + const isNestedModule = stringContains(fragment, directorySeparator); const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined; // Get modules that the type checker picked up diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index c16a290a30f30..124a1f720bd79 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -660,7 +660,7 @@ namespace ts.refactor.extractSymbol { function getUniqueName(baseName: string, fileText: string): string { let nameText = baseName; - for (let i = 1; fileText.indexOf(nameText) !== -1; i++) { + for (let i = 1; stringContains(fileText, nameText); i++) { nameText = `${baseName}_${i}`; } return nameText; diff --git a/src/services/services.ts b/src/services/services.ts index bc733a4e2feb8..6bdc96d8b4d65 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1952,7 +1952,7 @@ namespace ts { function isNodeModulesFile(path: string): boolean { const node_modulesFolderName = "/node_modules/"; - return path.indexOf(node_modulesFolderName) !== -1; + return stringContains(path, node_modulesFolderName); } } From 52d7c7278d7b6d3995777980e73466d630b53837 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 17:14:32 -0700 Subject: [PATCH 104/246] Add comment about swallowing exception --- src/server/server.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index 7917f6fb544a6..f24251ee6ac90 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -753,11 +753,13 @@ namespace ts.server { const sys = ts.sys; // use watchGuard process on Windows when node version is 4 or later const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4; - const originalWatchDirectory = sys.watchDirectory; + const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); const noopWatcher: FileWatcher = { close: noop }; + // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function + // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher { try { - return originalWatchDirectory.call(sys, path, callback, recursive); + return originalWatchDirectory(path, callback, recursive); } catch (e) { logger.info(`Exception when creating directory watcher: ${e.message}`); From 856961b84ceb96098fba52ddac76c9d3ed0b0032 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Oct 2017 17:20:10 -0700 Subject: [PATCH 105/246] Add regression test for #18668 (#19085) --- .../castFunctionExpressionShouldBeParenthesized.js | 5 +++++ ...astFunctionExpressionShouldBeParenthesized.symbols | 4 ++++ .../castFunctionExpressionShouldBeParenthesized.types | 11 +++++++++++ .../castFunctionExpressionShouldBeParenthesized.ts | 1 + 4 files changed, 21 insertions(+) create mode 100644 tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.js create mode 100644 tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.symbols create mode 100644 tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.types create mode 100644 tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts diff --git a/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.js b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.js new file mode 100644 index 0000000000000..e96b93bae8506 --- /dev/null +++ b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.js @@ -0,0 +1,5 @@ +//// [castFunctionExpressionShouldBeParenthesized.ts] +(function a() { } as any)().foo() + +//// [castFunctionExpressionShouldBeParenthesized.js] +(function a() { }().foo()); diff --git a/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.symbols b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.symbols new file mode 100644 index 0000000000000..975a9480c3ccd --- /dev/null +++ b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.symbols @@ -0,0 +1,4 @@ +=== tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts === +(function a() { } as any)().foo() +>a : Symbol(a, Decl(castFunctionExpressionShouldBeParenthesized.ts, 0, 1)) + diff --git a/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.types b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.types new file mode 100644 index 0000000000000..337c5163ff26d --- /dev/null +++ b/tests/baselines/reference/castFunctionExpressionShouldBeParenthesized.types @@ -0,0 +1,11 @@ +=== tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts === +(function a() { } as any)().foo() +>(function a() { } as any)().foo() : any +>(function a() { } as any)().foo : any +>(function a() { } as any)() : any +>(function a() { } as any) : any +>function a() { } as any : any +>function a() { } : () => void +>a : () => void +>foo : any + diff --git a/tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts b/tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts new file mode 100644 index 0000000000000..3fb1aaf7079de --- /dev/null +++ b/tests/cases/compiler/castFunctionExpressionShouldBeParenthesized.ts @@ -0,0 +1 @@ +(function a() { } as any)().foo() \ No newline at end of file From 5a1d846e76d01069d8fc6af9e3edf16c66990829 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 10 Oct 2017 17:34:16 -0700 Subject: [PATCH 106/246] Properly account for possibly referenced type parameters --- src/compiler/checker.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58ac3bc52c0bc..ed131c8936c44 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8258,11 +8258,11 @@ namespace ts { // The first time an anonymous type is instantiated we compute and store a list of the type // parameters that are in scope (and therefore potentially referenced). For type literals that // aren't the right hand side of a generic type alias declaration we optimize by reducing the - // set of type parameters to those that are actually referenced somewhere in the literal. + // set of type parameters to those that are possibly referenced in the literal. const declaration = symbol.declarations[0]; const outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true) || emptyArray; typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ? - filter(outerTypeParameters, tp => isTypeParameterReferencedWithin(tp, declaration)) : + filter(outerTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) : outerTypeParameters; links.typeParameters = typeParameters; if (typeParameters.length) { @@ -8288,8 +8288,17 @@ namespace ts { return type; } - function isTypeParameterReferencedWithin(tp: TypeParameter, node: Node) { - return tp.isThisType ? forEachChild(node, checkThis) : forEachChild(node, checkIdentifier); + function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) { + // If the type parameter doesn't have exactly one declaration, if there are invening statement blocks + // between the node and the type parameter declaration, or if the node contains actual references to the + // type parameter, we consider the type parameter possibly referenced. + if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { + const container = tp.symbol.declarations[0].parent; + if (findAncestor(node, n => n.kind === SyntaxKind.Block ? "quit" : n === container)) { + return tp.isThisType ? forEachChild(node, checkThis) : forEachChild(node, checkIdentifier); + } + } + return true; function checkThis(node: Node): boolean { return node.kind === SyntaxKind.ThisType || forEachChild(node, checkThis); } From 83020dbbd6c43ecdbebe7bf6a65b573eb6038aa3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 10 Oct 2017 17:34:32 -0700 Subject: [PATCH 107/246] Add regression test --- .../indirectTypeParameterReferences.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/cases/compiler/indirectTypeParameterReferences.ts diff --git a/tests/cases/compiler/indirectTypeParameterReferences.ts b/tests/cases/compiler/indirectTypeParameterReferences.ts new file mode 100644 index 0000000000000..210a599354dc3 --- /dev/null +++ b/tests/cases/compiler/indirectTypeParameterReferences.ts @@ -0,0 +1,24 @@ +// Repro from #19043 + +type B = {b: string} + +const flowtypes = (b: B) => { + type Combined = A & B + + const combined = (fn: (combined: Combined) => void) => null + const literal = (fn: (aPlusB: A & B) => void) => null + + return {combined, literal} +} + +const {combined, literal} = flowtypes<{a: string}>({b: 'b-value'}) + +literal(aPlusB => { + aPlusB.b + aPlusB.a +}) + +combined(comb => { + comb.b + comb.a +}) From d815ba13f8b67847935c386102288e754f3894de Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 10 Oct 2017 17:34:44 -0700 Subject: [PATCH 108/246] Accept new baselines --- .../indirectTypeParameterReferences.js | 43 +++++++++ .../indirectTypeParameterReferences.symbols | 75 ++++++++++++++++ .../indirectTypeParameterReferences.types | 88 +++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 tests/baselines/reference/indirectTypeParameterReferences.js create mode 100644 tests/baselines/reference/indirectTypeParameterReferences.symbols create mode 100644 tests/baselines/reference/indirectTypeParameterReferences.types diff --git a/tests/baselines/reference/indirectTypeParameterReferences.js b/tests/baselines/reference/indirectTypeParameterReferences.js new file mode 100644 index 0000000000000..e6e807a472038 --- /dev/null +++ b/tests/baselines/reference/indirectTypeParameterReferences.js @@ -0,0 +1,43 @@ +//// [indirectTypeParameterReferences.ts] +// Repro from #19043 + +type B = {b: string} + +const flowtypes = (b: B) => { + type Combined = A & B + + const combined = (fn: (combined: Combined) => void) => null + const literal = (fn: (aPlusB: A & B) => void) => null + + return {combined, literal} +} + +const {combined, literal} = flowtypes<{a: string}>({b: 'b-value'}) + +literal(aPlusB => { + aPlusB.b + aPlusB.a +}) + +combined(comb => { + comb.b + comb.a +}) + + +//// [indirectTypeParameterReferences.js] +// Repro from #19043 +var flowtypes = function (b) { + var combined = function (fn) { return null; }; + var literal = function (fn) { return null; }; + return { combined: combined, literal: literal }; +}; +var _a = flowtypes({ b: 'b-value' }), combined = _a.combined, literal = _a.literal; +literal(function (aPlusB) { + aPlusB.b; + aPlusB.a; +}); +combined(function (comb) { + comb.b; + comb.a; +}); diff --git a/tests/baselines/reference/indirectTypeParameterReferences.symbols b/tests/baselines/reference/indirectTypeParameterReferences.symbols new file mode 100644 index 0000000000000..0cb091a86224a --- /dev/null +++ b/tests/baselines/reference/indirectTypeParameterReferences.symbols @@ -0,0 +1,75 @@ +=== tests/cases/compiler/indirectTypeParameterReferences.ts === +// Repro from #19043 + +type B = {b: string} +>B : Symbol(B, Decl(indirectTypeParameterReferences.ts, 0, 0)) +>b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 2, 10)) + +const flowtypes = (b: B) => { +>flowtypes : Symbol(flowtypes, Decl(indirectTypeParameterReferences.ts, 4, 5)) +>A : Symbol(A, Decl(indirectTypeParameterReferences.ts, 4, 19)) +>b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 4, 22)) +>B : Symbol(B, Decl(indirectTypeParameterReferences.ts, 0, 0)) + + type Combined = A & B +>Combined : Symbol(Combined, Decl(indirectTypeParameterReferences.ts, 4, 32)) +>A : Symbol(A, Decl(indirectTypeParameterReferences.ts, 4, 19)) +>B : Symbol(B, Decl(indirectTypeParameterReferences.ts, 0, 0)) + + const combined = (fn: (combined: Combined) => void) => null +>combined : Symbol(combined, Decl(indirectTypeParameterReferences.ts, 7, 7)) +>fn : Symbol(fn, Decl(indirectTypeParameterReferences.ts, 7, 20)) +>combined : Symbol(combined, Decl(indirectTypeParameterReferences.ts, 7, 25)) +>Combined : Symbol(Combined, Decl(indirectTypeParameterReferences.ts, 4, 32)) + + const literal = (fn: (aPlusB: A & B) => void) => null +>literal : Symbol(literal, Decl(indirectTypeParameterReferences.ts, 8, 7)) +>fn : Symbol(fn, Decl(indirectTypeParameterReferences.ts, 8, 19)) +>aPlusB : Symbol(aPlusB, Decl(indirectTypeParameterReferences.ts, 8, 24)) +>A : Symbol(A, Decl(indirectTypeParameterReferences.ts, 4, 19)) +>B : Symbol(B, Decl(indirectTypeParameterReferences.ts, 0, 0)) + + return {combined, literal} +>combined : Symbol(combined, Decl(indirectTypeParameterReferences.ts, 10, 10)) +>literal : Symbol(literal, Decl(indirectTypeParameterReferences.ts, 10, 19)) +} + +const {combined, literal} = flowtypes<{a: string}>({b: 'b-value'}) +>combined : Symbol(combined, Decl(indirectTypeParameterReferences.ts, 13, 7)) +>literal : Symbol(literal, Decl(indirectTypeParameterReferences.ts, 13, 16)) +>flowtypes : Symbol(flowtypes, Decl(indirectTypeParameterReferences.ts, 4, 5)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 13, 39)) +>b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 13, 52)) + +literal(aPlusB => { +>literal : Symbol(literal, Decl(indirectTypeParameterReferences.ts, 13, 16)) +>aPlusB : Symbol(aPlusB, Decl(indirectTypeParameterReferences.ts, 15, 8)) + + aPlusB.b +>aPlusB.b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 2, 10)) +>aPlusB : Symbol(aPlusB, Decl(indirectTypeParameterReferences.ts, 15, 8)) +>b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 2, 10)) + + aPlusB.a +>aPlusB.a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 13, 39)) +>aPlusB : Symbol(aPlusB, Decl(indirectTypeParameterReferences.ts, 15, 8)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 13, 39)) + +}) + +combined(comb => { +>combined : Symbol(combined, Decl(indirectTypeParameterReferences.ts, 13, 7)) +>comb : Symbol(comb, Decl(indirectTypeParameterReferences.ts, 20, 9)) + + comb.b +>comb.b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 2, 10)) +>comb : Symbol(comb, Decl(indirectTypeParameterReferences.ts, 20, 9)) +>b : Symbol(b, Decl(indirectTypeParameterReferences.ts, 2, 10)) + + comb.a +>comb.a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 13, 39)) +>comb : Symbol(comb, Decl(indirectTypeParameterReferences.ts, 20, 9)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 13, 39)) + +}) + diff --git a/tests/baselines/reference/indirectTypeParameterReferences.types b/tests/baselines/reference/indirectTypeParameterReferences.types new file mode 100644 index 0000000000000..2a8ac9a8b0891 --- /dev/null +++ b/tests/baselines/reference/indirectTypeParameterReferences.types @@ -0,0 +1,88 @@ +=== tests/cases/compiler/indirectTypeParameterReferences.ts === +// Repro from #19043 + +type B = {b: string} +>B : B +>b : string + +const flowtypes = (b: B) => { +>flowtypes : (b: B) => { combined: (fn: (combined: A & B) => void) => any; literal: (fn: (aPlusB: A & B) => void) => any; } +>(b: B) => { type Combined = A & B const combined = (fn: (combined: Combined) => void) => null const literal = (fn: (aPlusB: A & B) => void) => null return {combined, literal}} : (b: B) => { combined: (fn: (combined: A & B) => void) => any; literal: (fn: (aPlusB: A & B) => void) => any; } +>A : A +>b : B +>B : B + + type Combined = A & B +>Combined : A & B +>A : A +>B : B + + const combined = (fn: (combined: Combined) => void) => null +>combined : (fn: (combined: A & B) => void) => any +>(fn: (combined: Combined) => void) => null : (fn: (combined: A & B) => void) => any +>fn : (combined: A & B) => void +>combined : A & B +>Combined : A & B +>null : null + + const literal = (fn: (aPlusB: A & B) => void) => null +>literal : (fn: (aPlusB: A & B) => void) => any +>(fn: (aPlusB: A & B) => void) => null : (fn: (aPlusB: A & B) => void) => any +>fn : (aPlusB: A & B) => void +>aPlusB : A & B +>A : A +>B : B +>null : null + + return {combined, literal} +>{combined, literal} : { combined: (fn: (combined: A & B) => void) => any; literal: (fn: (aPlusB: A & B) => void) => any; } +>combined : (fn: (combined: A & B) => void) => any +>literal : (fn: (aPlusB: A & B) => void) => any +} + +const {combined, literal} = flowtypes<{a: string}>({b: 'b-value'}) +>combined : (fn: (combined: { a: string; } & B) => void) => any +>literal : (fn: (aPlusB: { a: string; } & B) => void) => any +>flowtypes<{a: string}>({b: 'b-value'}) : { combined: (fn: (combined: { a: string; } & B) => void) => any; literal: (fn: (aPlusB: { a: string; } & B) => void) => any; } +>flowtypes : (b: B) => { combined: (fn: (combined: A & B) => void) => any; literal: (fn: (aPlusB: A & B) => void) => any; } +>a : string +>{b: 'b-value'} : { b: string; } +>b : string +>'b-value' : "b-value" + +literal(aPlusB => { +>literal(aPlusB => { aPlusB.b aPlusB.a}) : any +>literal : (fn: (aPlusB: { a: string; } & B) => void) => any +>aPlusB => { aPlusB.b aPlusB.a} : (aPlusB: { a: string; } & B) => void +>aPlusB : { a: string; } & B + + aPlusB.b +>aPlusB.b : string +>aPlusB : { a: string; } & B +>b : string + + aPlusB.a +>aPlusB.a : string +>aPlusB : { a: string; } & B +>a : string + +}) + +combined(comb => { +>combined(comb => { comb.b comb.a}) : any +>combined : (fn: (combined: { a: string; } & B) => void) => any +>comb => { comb.b comb.a} : (comb: { a: string; } & B) => void +>comb : { a: string; } & B + + comb.b +>comb.b : string +>comb : { a: string; } & B +>b : string + + comb.a +>comb.a : string +>comb : { a: string; } & B +>a : string + +}) + From c5b4f5e7e72516f2cb946a189e1b06fed17ef199 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 16:28:44 -0700 Subject: [PATCH 109/246] Use filterMutate instead of removeWhere --- src/harness/unittests/telemetry.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index d2a54fdc1bb96..25120af45c1d2 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -257,11 +257,12 @@ namespace ts.projectSystem { getEventsWithName(eventName: T["eventName"]): ReadonlyArray { let events: T[]; - removeWhere(this.events, event => { + filterMutate(this.events, event => { if (event.eventName === eventName) { (events || (events = [])).push(event as T); - return true; + return false; } + return true; }); return events || emptyArray; } @@ -291,14 +292,15 @@ namespace ts.projectSystem { getEvent(eventName: T["eventName"]): T["data"] { let event: server.ProjectServiceEvent; - removeWhere(this.events, e => { + filterMutate(this.events, e => { if (e.eventName === eventName) { if (event) { assert(false, "more than one event found"); } event = e; - return true; + return false; } + return true; }); assert.equal(event.eventName, eventName); return event.data; From bb4abbd95ecb20ba3e7e4ca12dfe41b1c80533c5 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 17:37:02 -0700 Subject: [PATCH 110/246] Do not generate config file diagnostics event when the file opened doesnot belong to the configured project --- src/harness/unittests/tsserverProjectSystem.ts | 11 ++--------- src/server/editorServices.ts | 10 ++++------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 3d244fd30f8ba..04b848e7cdf71 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -3168,7 +3168,7 @@ namespace ts.projectSystem { serverEventManager.checkEventCountOfType("configFileDiag", 3); }); - it("are generated when the config file doesnot include file opened but has errors", () => { + it("are not generated when the config file doesnot include file opened and config file has errors", () => { const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", @@ -3195,14 +3195,7 @@ namespace ts.projectSystem { eventHandler: serverEventManager.handler }); openFilesForSession([file2], session); - serverEventManager.checkEventCountOfType("configFileDiag", 1); - for (const event of serverEventManager.events) { - if (event.eventName === "configFileDiag") { - assert.equal(event.data.configFileName, configFile.path); - assert.equal(event.data.triggerFile, file2.path); - return; - } - } + serverEventManager.checkEventCountOfType("configFileDiag", 0); }); it("are not generated when the config file doesnot include file opened and doesnt contain any errors", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index fd2297473908a..765a31884437d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1933,12 +1933,10 @@ namespace ts.server { // At this point if file is part of any any configured or external project, then it would be present in the containing projects // So if it still doesnt have any containing projects, it needs to be part of inferred project if (info.isOrphan()) { - // Since the file isnt part of configured project, - // report config file and its error only if config file found had errors (and hence may be didnt include the file) - if (sendConfigFileDiagEvent && !project.getAllProjectErrors().length) { - configFileName = undefined; - sendConfigFileDiagEvent = false; - } + // Since the file isnt part of configured project, do not send config file event + configFileName = undefined; + sendConfigFileDiagEvent = false; + this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); } this.addToListOfOpenFiles(info); From d0168af142dfcaa0310a6825cfd67e5e0e51da1c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 10 Oct 2017 17:59:43 -0700 Subject: [PATCH 111/246] Functioning parallel unittests (#18956) --- src/harness/parallel/host.ts | 48 ++++++++++++++++++++------- src/harness/parallel/shared.ts | 4 +-- src/harness/parallel/worker.ts | 60 ++++++++++++++++++++++++---------- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index 2aaa4f7872837..d7bba70408e7f 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -38,20 +38,45 @@ namespace Harness.Parallel.Host { return undefined; } - function hashName(runner: TestRunnerKind, test: string) { + function hashName(runner: TestRunnerKind | "unittest", test: string) { return `tsrunner-${runner}://${test}`; } + let tasks: { runner: TestRunnerKind | "unittest", file: string, size: number }[] = []; + const newTasks: { runner: TestRunnerKind | "unittest", file: string, size: number }[] = []; + let unknownValue: string | undefined; export function start() { + const perfData = readSavedPerfData(configOption); + let totalCost = 0; + if (runUnitTests) { + (global as any).describe = (suiteName: string) => { + // Note, sub-suites are not indexed (we assume such granularity is not required) + let size = 0; + if (perfData) { + size = perfData[hashName("unittest", suiteName)]; + if (size === undefined) { + newTasks.push({ runner: "unittest", file: suiteName, size: 0 }); + unknownValue = suiteName; + return; + } + } + tasks.push({ runner: "unittest", file: suiteName, size }); + totalCost += size; + }; + } + else { + (global as any).describe = ts.noop; + } + + setTimeout(() => startDelayed(perfData, totalCost), 0); // Do real startup on next tick, so all unit tests have been collected + } + + function startDelayed(perfData: {[testHash: string]: number}, totalCost: number) { initializeProgressBarsDependencies(); - console.log("Discovering tests..."); + console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : ".")); + console.log("Discovering runner-based tests..."); const discoverStart = +(new Date()); const { statSync }: { statSync(path: string): { size: number }; } = require("fs"); - let tasks: { runner: TestRunnerKind, file: string, size: number }[] = []; - const newTasks: { runner: TestRunnerKind, file: string, size: number }[] = []; - const perfData = readSavedPerfData(configOption); - let totalCost = 0; - let unknownValue: string | undefined; for (const runner of runners) { const files = runner.enumerateTestFiles(); for (const file of files) { @@ -87,8 +112,7 @@ namespace Harness.Parallel.Host { } tasks.sort((a, b) => a.size - b.size); tasks = tasks.concat(newTasks); - // 1 fewer batches than threads to account for unittests running on the final thread - const batchCount = runners.length === 1 ? workerCount : workerCount - 1; + const batchCount = workerCount; const packfraction = 0.9; const chunkSize = 1000; // ~1KB or 1s for sending batches near the end of a test const batchSize = (totalCost / workerCount) * packfraction; // Keep spare tests for unittest thread in reserve @@ -113,7 +137,7 @@ namespace Harness.Parallel.Host { let closedWorkers = 0; for (let i = 0; i < workerCount; i++) { // TODO: Just send the config over the IPC channel or in the command line arguments - const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length === 1 ? false : i === workerCount - 1 }; + const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length !== 1 }; const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`); Harness.IO.writeFile(configPath, JSON.stringify(config)); const child = fork(__filename, [`--config="${configPath}"`]); @@ -187,7 +211,7 @@ namespace Harness.Parallel.Host { // It's only really worth doing an initial batching if there are a ton of files to go through if (totalFiles > 1000) { console.log("Batching initial test lists..."); - const batches: { runner: TestRunnerKind, file: string, size: number }[][] = new Array(batchCount); + const batches: { runner: TestRunnerKind | "unittest", file: string, size: number }[][] = new Array(batchCount); const doneBatching = new Array(batchCount); let scheduledTotal = 0; batcher: while (true) { @@ -230,7 +254,7 @@ namespace Harness.Parallel.Host { if (payload) { worker.send({ type: "batch", payload }); } - else { // Unittest thread - send off just one test + else { // Out of batches, send off just one test const payload = tasks.pop(); ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios worker.send({ type: "test", payload }); diff --git a/src/harness/parallel/shared.ts b/src/harness/parallel/shared.ts index 85d885c14a1e8..2eb7777f82870 100644 --- a/src/harness/parallel/shared.ts +++ b/src/harness/parallel/shared.ts @@ -1,14 +1,14 @@ /// /// namespace Harness.Parallel { - export type ParallelTestMessage = { type: "test", payload: { runner: TestRunnerKind, file: string } } | never; + export type ParallelTestMessage = { type: "test", payload: { runner: TestRunnerKind | "unittest", file: string } } | never; export type ParallelBatchMessage = { type: "batch", payload: ParallelTestMessage["payload"][] } | never; export type ParallelCloseMessage = { type: "close" } | never; export type ParallelHostMessage = ParallelTestMessage | ParallelCloseMessage | ParallelBatchMessage; export type ParallelErrorMessage = { type: "error", payload: { error: string, stack: string, name?: string[] } } | never; export type ErrorInfo = ParallelErrorMessage["payload"] & { name: string[] }; - export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind, file: string } } | never; + export type ParallelResultMessage = { type: "result", payload: { passing: number, errors: ErrorInfo[], duration: number, runner: TestRunnerKind | "unittest", file: string } } | never; export type ParallelBatchProgressMessage = { type: "progress", payload: ParallelResultMessage["payload"] } | never; export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage; } \ No newline at end of file diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index 7e95831535acb..c32b9660a3911 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -1,22 +1,13 @@ namespace Harness.Parallel.Worker { let errors: ErrorInfo[] = []; let passing = 0; - let reportedUnitTests = false; type Executor = {name: string, callback: Function, kind: "suite" | "test"} | never; function resetShimHarnessAndExecute(runner: RunnerBase) { - if (reportedUnitTests) { - errors = []; - passing = 0; - testList.length = 0; - } - reportedUnitTests = true; - if (testList.length) { - // Execute unit tests - testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind)); - testList.length = 0; - } + errors = []; + passing = 0; + testList.length = 0; const start = +(new Date()); runner.initializeTests(); testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind)); @@ -226,13 +217,46 @@ namespace Harness.Parallel.Worker { shimMochaHarness(); } - function handleTest(runner: TestRunnerKind, file: string) { - if (!runners.has(runner)) { - runners.set(runner, createRunner(runner)); + function handleTest(runner: TestRunnerKind | "unittest", file: string) { + collectUnitTestsIfNeeded(); + if (runner === unittest) { + return executeUnitTest(file); + } + else { + if (!runners.has(runner)) { + runners.set(runner, createRunner(runner)); + } + const instance = runners.get(runner); + instance.tests = [file]; + return { ...resetShimHarnessAndExecute(instance), runner, file }; } - const instance = runners.get(runner); - instance.tests = [file]; - return { ...resetShimHarnessAndExecute(instance), runner, file }; } } + + const unittest: "unittest" = "unittest"; + let unitTests: {[name: string]: Function}; + function collectUnitTestsIfNeeded() { + if (!unitTests && testList.length) { + unitTests = {}; + for (const test of testList) { + unitTests[test.name] = test.callback; + } + testList.length = 0; + } + } + + function executeUnitTest(name: string) { + if (!unitTests) { + throw new Error(`Asked to run unit test ${name}, but no unit tests were discovered!`); + } + if (unitTests[name]) { + errors = []; + passing = 0; + const start = +(new Date()); + executeSuiteCallback(name, unitTests[name]); + delete unitTests[name]; + return { file: name, runner: unittest, errors, passing, duration: +(new Date()) - start }; + } + throw new Error(`Unit test with name "${name}" was asked to be run, but such a test does not exist!`); + } } \ No newline at end of file From 0e2eb3a2b88628680ca3ef56703d3679a8439f80 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 18:25:26 -0700 Subject: [PATCH 112/246] Combine the event manager testing --- src/harness/unittests/telemetry.ts | 98 ++--------- .../unittests/tsserverProjectSystem.ts | 154 ++++++++++-------- 2 files changed, 101 insertions(+), 151 deletions(-) diff --git a/src/harness/unittests/telemetry.ts b/src/harness/unittests/telemetry.ts index 25120af45c1d2..9bb2db738013d 100644 --- a/src/harness/unittests/telemetry.ts +++ b/src/harness/unittests/telemetry.ts @@ -5,9 +5,9 @@ namespace ts.projectSystem { describe("project telemetry", () => { it("does nothing for inferred project", () => { const file = makeFile("/a.js"); - const et = new EventTracker([file]); + const et = new TestServerEventManager([file]); et.service.openClientFile(file.path); - assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); + et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent); }); it("only sends an event once", () => { @@ -15,7 +15,7 @@ namespace ts.projectSystem { const file2 = makeFile("/b.ts"); const tsconfig = makeFile("/a/tsconfig.json", {}); - const et = new EventTracker([file, file2, tsconfig]); + const et = new TestServerEventManager([file, file2, tsconfig]); et.service.openClientFile(file.path); et.assertProjectInfoTelemetryEvent({}, tsconfig.path); @@ -25,12 +25,12 @@ namespace ts.projectSystem { et.service.openClientFile(file2.path); checkNumberOfProjects(et.service, { inferredProjects: 1 }); - assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); + et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent); et.service.openClientFile(file.path); checkNumberOfProjects(et.service, { configuredProjects: 1, inferredProjects: 1 }); - assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0); + et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent); }); it("counts files by extension", () => { @@ -39,7 +39,7 @@ namespace ts.projectSystem { const compilerOptions: ts.CompilerOptions = { allowJs: true }; const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] }); - const et = new EventTracker([...files, notIncludedFile, tsconfig]); + const et = new TestServerEventManager([...files, notIncludedFile, tsconfig]); et.service.openClientFile(files[0].path); et.assertProjectInfoTelemetryEvent({ fileStats: { ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 }, @@ -50,7 +50,7 @@ namespace ts.projectSystem { it("works with external project", () => { const file1 = makeFile("/a.ts"); - const et = new EventTracker([file1]); + const et = new TestServerEventManager([file1]); const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true }; const projectFileName = "/hunter2/foo.csproj"; @@ -148,7 +148,7 @@ namespace ts.projectSystem { (compilerOptions as any).unknownCompilerOption = "hunter2"; // These are always ignored. const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] }); - const et = new EventTracker([file, tsconfig]); + const et = new TestServerEventManager([file, tsconfig]); et.service.openClientFile(file.path); et.assertProjectInfoTelemetryEvent({ @@ -168,7 +168,7 @@ namespace ts.projectSystem { compileOnSave: true, }); - const et = new EventTracker([tsconfig, file]); + const et = new TestServerEventManager([tsconfig, file]); et.service.openClientFile(file.path); et.assertProjectInfoTelemetryEvent({ extends: true, @@ -198,7 +198,7 @@ namespace ts.projectSystem { exclude: [], }, }); - const et = new EventTracker([jsconfig, file]); + const et = new TestServerEventManager([jsconfig, file]); et.service.openClientFile(file.path); et.assertProjectInfoTelemetryEvent({ projectId: Harness.mockHash("/jsconfig.json"), @@ -216,7 +216,7 @@ namespace ts.projectSystem { it("detects whether language service was disabled", () => { const file = makeFile("/a.js"); const tsconfig = makeFile("/jsconfig.json", {}); - const et = new EventTracker([tsconfig, file]); + const et = new TestServerEventManager([tsconfig, file]); et.host.getFileSize = () => server.maxProgramSizeForNonTsFiles + 1; et.service.openClientFile(file.path); et.getEvent(server.ProjectLanguageServiceStateEvent); @@ -235,83 +235,7 @@ namespace ts.projectSystem { }); }); - class EventTracker { - private events: server.ProjectServiceEvent[] = []; - readonly service: TestProjectService; - readonly host: projectSystem.TestServerHost; - - constructor(files: projectSystem.FileOrFolder[]) { - this.host = createServerHost(files); - this.service = createProjectService(this.host, { - eventHandler: event => { - this.events.push(event); - }, - }); - } - - getEvents(): ReadonlyArray { - const events = this.events; - this.events = []; - return events; - } - - getEventsWithName(eventName: T["eventName"]): ReadonlyArray { - let events: T[]; - filterMutate(this.events, event => { - if (event.eventName === eventName) { - (events || (events = [])).push(event as T); - return false; - } - return true; - }); - return events || emptyArray; - } - - assertProjectInfoTelemetryEvent(partial: Partial, configFile?: string): void { - assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), { - projectId: Harness.mockHash(configFile || "/tsconfig.json"), - fileStats: fileStats({ ts: 1 }), - compilerOptions: {}, - extends: false, - files: false, - include: false, - exclude: false, - compileOnSave: false, - typeAcquisition: { - enable: false, - exclude: false, - include: false, - }, - configFileName: "tsconfig.json", - projectType: "configured", - languageServiceEnabled: true, - version: ts.version, - ...partial, - }); - } - - getEvent(eventName: T["eventName"]): T["data"] { - let event: server.ProjectServiceEvent; - filterMutate(this.events, e => { - if (e.eventName === eventName) { - if (event) { - assert(false, "more than one event found"); - } - event = e; - return false; - } - return true; - }); - assert.equal(event.eventName, eventName); - return event.data; - } - } - function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder { return { path, content: isString(content) ? "" : JSON.stringify(content) }; } - - function fileStats(nonZeroStats: Partial): server.FileStats { - return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats }; - } } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 04b848e7cdf71..d5b9b9d62fcf4 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -132,16 +132,78 @@ namespace ts.projectSystem { return map(fileNames, toExternalFile); } - class TestServerEventManager { - public events: server.ProjectServiceEvent[] = []; + export function fileStats(nonZeroStats: Partial): server.FileStats { + return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats }; + } + + export class TestServerEventManager { + private events: server.ProjectServiceEvent[] = []; + readonly session: TestSession; + readonly service: server.ProjectService; + readonly host: projectSystem.TestServerHost; + constructor(files: projectSystem.FileOrFolder[]) { + this.host = createServerHost(files); + this.session = createSession(this.host, { + canUseEvents: true, + eventHandler: event => this.events.push(event), + }); + this.service = this.session.getProjectService(); + } + + getEvents(): ReadonlyArray { + const events = this.events; + this.events = []; + return events; + } + + getEvent(eventName: T["eventName"]): T["data"] { + let eventData: T["data"]; + filterMutate(this.events, e => { + if (e.eventName === eventName) { + if (eventData !== undefined) { + assert(false, "more than one event found"); + } + eventData = e.data; + return false; + } + return true; + }); + assert.isDefined(eventData); + return eventData; + } + + hasZeroEvent(eventName: T["eventName"]) { + const eventCount = countWhere(this.events, event => event.eventName === eventName); + assert.equal(eventCount, 0); + } - handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => { - this.events.push(event); + checkSingleConfigFileDiagEvent(configFileName: string, triggerFile: string) { + const eventData = this.getEvent(server.ConfigFileDiagEvent); + assert.equal(eventData.configFileName, configFileName); + assert.equal(eventData.triggerFile, triggerFile); } - checkEventCountOfType(eventType: "configFileDiag", expectedCount: number) { - const eventsOfType = filter(this.events, e => e.eventName === eventType); - assert.equal(eventsOfType.length, expectedCount, `The actual event counts of type ${eventType} is ${eventsOfType.length}, while expected ${expectedCount}`); + assertProjectInfoTelemetryEvent(partial: Partial, configFile?: string): void { + assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), { + projectId: Harness.mockHash(configFile || "/tsconfig.json"), + fileStats: fileStats({ ts: 1 }), + compilerOptions: {}, + extends: false, + files: false, + include: false, + exclude: false, + compileOnSave: false, + typeAcquisition: { + enable: false, + exclude: false, + include: false, + }, + configFileName: "tsconfig.json", + projectType: "configured", + languageServiceEnabled: true, + version: ts.version, + ...partial, + }); } } @@ -3076,7 +3138,6 @@ namespace ts.projectSystem { describe("Configure file diagnostics events", () => { it("are generated when the config file has errors", () => { - const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -3090,26 +3151,12 @@ namespace ts.projectSystem { } }` }; - - const host = createServerHost([file, configFile]); - const session = createSession(host, { - canUseEvents: true, - eventHandler: serverEventManager.handler - }); - openFilesForSession([file], session); - serverEventManager.checkEventCountOfType("configFileDiag", 1); - - for (const event of serverEventManager.events) { - if (event.eventName === "configFileDiag") { - assert.equal(event.data.configFileName, configFile.path); - assert.equal(event.data.triggerFile, file.path); - return; - } - } + const serverEventManager = new TestServerEventManager([file, configFile]); + openFilesForSession([file], serverEventManager.session); + serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path); }); it("are generated when the config file doesn't have errors", () => { - const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -3120,18 +3167,12 @@ namespace ts.projectSystem { "compilerOptions": {} }` }; - - const host = createServerHost([file, configFile]); - const session = createSession(host, { - canUseEvents: true, - eventHandler: serverEventManager.handler - }); - openFilesForSession([file], session); - serverEventManager.checkEventCountOfType("configFileDiag", 1); + const serverEventManager = new TestServerEventManager([file, configFile]); + openFilesForSession([file], serverEventManager.session); + serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path); }); it("are generated when the config file changes", () => { - const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -3143,33 +3184,28 @@ namespace ts.projectSystem { }` }; - const host = createServerHost([file, configFile]); - const session = createSession(host, { - canUseEvents: true, - eventHandler: serverEventManager.handler - }); - openFilesForSession([file], session); - serverEventManager.checkEventCountOfType("configFileDiag", 1); + const serverEventManager = new TestServerEventManager([file, configFile]); + openFilesForSession([file], serverEventManager.session); + serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path); configFile.content = `{ "compilerOptions": { "haha": 123 } }`; - host.reloadFS([file, configFile]); - host.runQueuedTimeoutCallbacks(); - serverEventManager.checkEventCountOfType("configFileDiag", 2); + serverEventManager.host.reloadFS([file, configFile]); + serverEventManager.host.runQueuedTimeoutCallbacks(); + serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, configFile.path); configFile.content = `{ "compilerOptions": {} }`; - host.reloadFS([file, configFile]); - host.runQueuedTimeoutCallbacks(); - serverEventManager.checkEventCountOfType("configFileDiag", 3); + serverEventManager.host.reloadFS([file, configFile]); + serverEventManager.host.runQueuedTimeoutCallbacks(); + serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, configFile.path); }); it("are not generated when the config file doesnot include file opened and config file has errors", () => { - const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -3188,18 +3224,12 @@ namespace ts.projectSystem { "files": ["app.ts"] }` }; - - const host = createServerHost([file, file2, libFile, configFile]); - const session = createSession(host, { - canUseEvents: true, - eventHandler: serverEventManager.handler - }); - openFilesForSession([file2], session); - serverEventManager.checkEventCountOfType("configFileDiag", 0); + const serverEventManager = new TestServerEventManager([file, file2, libFile, configFile]); + openFilesForSession([file2], serverEventManager.session); + serverEventManager.hasZeroEvent("configFileDiag"); }); it("are not generated when the config file doesnot include file opened and doesnt contain any errors", () => { - const serverEventManager = new TestServerEventManager(); const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -3215,13 +3245,9 @@ namespace ts.projectSystem { }` }; - const host = createServerHost([file, file2, libFile, configFile]); - const session = createSession(host, { - canUseEvents: true, - eventHandler: serverEventManager.handler - }); - openFilesForSession([file2], session); - serverEventManager.checkEventCountOfType("configFileDiag", 0); + const serverEventManager = new TestServerEventManager([file, file2, libFile, configFile]); + openFilesForSession([file2], serverEventManager.session); + serverEventManager.hasZeroEvent("configFileDiag"); }); }); From 9767d77143b89ea62b6a48bb8163ba68ab27213f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 18:41:45 -0700 Subject: [PATCH 113/246] Update comment on emit handler functions --- src/compiler/builder.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 03eb5b7e8aee9..093c6ec4d03ee 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -73,12 +73,17 @@ namespace ts { */ onRemoveSourceFile(path: Path): void; /** - * Called when sourceFile is changed + * For all source files, either "onUpdateSourceFile" or "onUpdateSourceFileWithSameVersion" will be called. + * If the builder is sure that the source file needs an update, "onUpdateSourceFile" will be called; + * otherwise "onUpdateSourceFileWithSameVersion" will be called. + * This should return whether the source file should be marked as changed (meaning that something associated with file has changed, e.g. module resolution) */ onUpdateSourceFile(program: Program, sourceFile: SourceFile): void; /** - * Called when source file has not changed - * If returned true, builder will mark the file as changed (noting that something associated with file has changed eg. module resolution) + * For all source files, either "onUpdateSourceFile" or "onUpdateSourceFileWithSameVersion" will be called. + * If the builder is sure that the source file needs an update, "onUpdateSourceFile" will be called; + * otherwise "onUpdateSourceFileWithSameVersion" will be called. + * This should return whether the source file should be marked as changed (meaning that something associated with file has changed, e.g. module resolution) */ onUpdateSourceFileWithSameVersion(program: Program, sourceFile: SourceFile): boolean; /** From 993890f06c422ab7fc016e07604f2ef0e00311c5 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 20:19:46 -0700 Subject: [PATCH 114/246] Verify errors more correctly in tsc-watch mode --- src/harness/unittests/tscWatchMode.ts | 353 ++++++++++++---------- src/harness/virtualFileSystemWithWatch.ts | 8 +- 2 files changed, 193 insertions(+), 168 deletions(-) diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 31d79df21c13b..b25a7b1eb53c2 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -80,6 +80,92 @@ namespace ts.tscWatch { checkOutputDoesNotContain(host, expectedNonAffectedFiles); } + function checkOutputErrors(host: WatchedSystem, errors?: ReadonlyArray, isInitial?: true, skipWaiting?: true) { + const outputs = host.getOutput(); + const expectedOutputCount = (isInitial ? 0 : 1) + (errors ? errors.length : 0) + (skipWaiting ? 0 : 1); + assert.equal(outputs.length, expectedOutputCount, "Outputs = " + outputs.toString()); + let index = 0; + if (!isInitial) { + assertWatchDiagnosticAt(host, index, Diagnostics.File_change_detected_Starting_incremental_compilation); + index++; + } + forEach(errors, error => { + assertDiagnosticAt(host, index, error); + index++; + }); + if (!skipWaiting) { + assertWatchDiagnosticAt(host, index, Diagnostics.Compilation_complete_Watching_for_file_changes); + } + host.clearOutput(); + } + + function assertDiagnosticAt(host: WatchedSystem, outputAt: number, diagnostic: Diagnostic) { + const output = host.getOutput()[outputAt]; + assert.equal(output, formatDiagnostic(diagnostic, host), "outputs[" + outputAt + "] is " + output); + } + + function assertWatchDiagnosticAt(host: WatchedSystem, outputAt: number, diagnosticMessage: DiagnosticMessage) { + const output = host.getOutput()[outputAt]; + assert.isTrue(endsWith(output, getWatchDiagnosticWithoutDate(host, diagnosticMessage)), "outputs[" + outputAt + "] is " + output); + } + + function getWatchDiagnosticWithoutDate(host: WatchedSystem, diagnosticMessage: DiagnosticMessage) { + return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`; + } + + function getDiagnosticOfFileFrom(file: SourceFile, text: string, start: number, length: number, message: DiagnosticMessage): Diagnostic { + return { + file, + start, + length, + + messageText: text, + category: message.category, + code: message.code, + }; + } + + function getDiagnosticWithoutFile(message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic { + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 1) { + text = formatStringFromArgs(text, arguments, 1); + } + + return getDiagnosticOfFileFrom(/*file*/ undefined, text, /*start*/ undefined, /*length*/ undefined, message); + } + + function getDiagnosticOfFile(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic { + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 4) { + text = formatStringFromArgs(text, arguments, 4); + } + + return getDiagnosticOfFileFrom(file, text, start, length, message); + } + + function getUnknownCompilerOption(program: Program, configFile: FileOrFolder, option: string) { + const quotedOption = `"${option}"`; + return getDiagnosticOfFile(program.getCompilerOptions().configFile, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option); + } + + function getDiagnosticOfFileFromProgram(program: Program, filePath: string, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic { + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 5) { + text = formatStringFromArgs(text, arguments, 5); + } + + return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())), + text, start, length, message); + } + + function getDiagnosticModuleNotFoundOfFile(program: Program, file: FileOrFolder, moduleName: string) { + const quotedModuleName = `"${moduleName}"`; + return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0, moduleName); + } + describe("tsc-watch program updates", () => { const commonFile1: FileOrFolder = { path: "/a/b/commonFile1.ts", @@ -233,9 +319,10 @@ namespace ts.tscWatch { }); it("handles the missing files - that were added to program because they were added with /// { + const commonFile2Name = "commonFile2.ts"; const file1: FileOrFolder = { path: "/a/b/commonFile1.ts", - content: `/// + content: `/// let x = y` }; const host = createWatchedSystem([file1, libFile]); @@ -243,18 +330,16 @@ namespace ts.tscWatch { checkProgramRootFiles(watch(), [file1.path]); checkProgramActualFiles(watch(), [file1.path, libFile.path]); - const errors = [ - `a/b/commonFile1.ts(1,22): error TS6053: File '${commonFile2.path}' not found.${host.newLine}`, - `a/b/commonFile1.ts(2,29): error TS2304: Cannot find name 'y'.${host.newLine}` - ]; - checkOutputContains(host, errors); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path), + getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y") + ], /*isInitial*/ true); host.reloadFS([file1, commonFile2, libFile]); host.runQueuedTimeoutCallbacks(); checkProgramRootFiles(watch(), [file1.path]); checkProgramActualFiles(watch(), [file1.path, libFile.path, commonFile2.path]); - checkOutputDoesNotContain(host, errors); + checkOutputErrors(host); }); it("should reflect change in config file", () => { @@ -578,17 +663,19 @@ namespace ts.tscWatch { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: {} }) }; - const host = createWatchedSystem([file1, file2, config]); + const host = createWatchedSystem([file1, file2, libFile, config]); const watch = createWatchModeWithConfigFile(config.path, host); - checkProgramActualFiles(watch(), [file1.path, file2.path]); + checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); - host.clearOutput(); - host.reloadFS([file1, file2]); + host.reloadFS([file1, file2, libFile]); host.checkTimeoutQueueLengthAndRun(1); assert.equal(host.exitCode, ExitStatus.DiagnosticsPresent_OutputsSkipped); - checkOutputContains(host, [`error TS6053: File '${config.path}' not found.${host.newLine}`]); + checkOutputErrors(host, [ + getDiagnosticWithoutFile(Diagnostics.File_0_not_found, config.path) + ], /*isInitial*/ undefined, /*skipWaiting*/ true); }); it("Proper errors: document is not contained in project", () => { @@ -687,25 +774,25 @@ namespace ts.tscWatch { }; const file1 = { path: "/a/b/file1.ts", - content: "import * as T from './moduleFile'; T.bar();" + content: 'import * as T from "./moduleFile"; T.bar();' }; const host = createWatchedSystem([moduleFile, file1, libFile]); - createWatchModeWithoutConfigFile([file1.path], host); - const error = "a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.\n"; - checkOutputDoesNotContain(host, [error]); + const watch = createWatchModeWithoutConfigFile([file1.path], host); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); const moduleFileOldPath = moduleFile.path; const moduleFileNewPath = "/a/b/moduleFile1.ts"; moduleFile.path = moduleFileNewPath; host.reloadFS([moduleFile, file1, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputContains(host, [error]); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile") + ]); - host.clearOutput(); moduleFile.path = moduleFileOldPath; host.reloadFS([moduleFile, file1, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [error]); + checkOutputErrors(host); }); it("rename a module file and rename back should restore the states for configured projects", () => { @@ -715,31 +802,29 @@ namespace ts.tscWatch { }; const file1 = { path: "/a/b/file1.ts", - content: "import * as T from './moduleFile'; T.bar();" + content: 'import * as T from "./moduleFile"; T.bar();' }; const configFile = { path: "/a/b/tsconfig.json", content: `{}` }; const host = createWatchedSystem([moduleFile, file1, configFile, libFile]); - createWatchModeWithConfigFile(configFile.path, host); - - const error = "a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.\n"; - checkOutputDoesNotContain(host, [error]); + const watch = createWatchModeWithConfigFile(configFile.path, host); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); const moduleFileOldPath = moduleFile.path; const moduleFileNewPath = "/a/b/moduleFile1.ts"; moduleFile.path = moduleFileNewPath; - host.clearOutput(); host.reloadFS([moduleFile, file1, configFile, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputContains(host, [error]); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile") + ]); - host.clearOutput(); moduleFile.path = moduleFileOldPath; host.reloadFS([moduleFile, file1, configFile, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [error]); + checkOutputErrors(host); }); it("types should load from config file path if config exists", () => { @@ -771,18 +856,18 @@ namespace ts.tscWatch { }; const file1 = { path: "/a/b/file1.ts", - content: "import * as T from './moduleFile'; T.bar();" + content: 'import * as T from "./moduleFile"; T.bar();' }; const host = createWatchedSystem([file1, libFile]); - createWatchModeWithoutConfigFile([file1.path], host); + const watch = createWatchModeWithoutConfigFile([file1.path], host); - const error = `a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.${host.newLine}`; - checkOutputContains(host, [error]); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile") + ], /*isInitial*/ true); host.reloadFS([file1, moduleFile, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [error]); + checkOutputErrors(host); }); it("Configure file diagnostics events are generated when the config file has errors", () => { @@ -801,14 +886,14 @@ namespace ts.tscWatch { }; const host = createWatchedSystem([file, configFile, libFile]); - createWatchModeWithConfigFile(configFile.path, host); - checkOutputContains(host, [ - `a/b/tsconfig.json(3,29): error TS5023: Unknown compiler option \'foo\'.${host.newLine}`, - `a/b/tsconfig.json(4,29): error TS5023: Unknown compiler option \'allowJS\'.${host.newLine}` - ]); + const watch = createWatchModeWithConfigFile(configFile.path, host); + checkOutputErrors(host, [ + getUnknownCompilerOption(watch(), configFile, "foo"), + getUnknownCompilerOption(watch(), configFile, "allowJS") + ], /*isInitial*/ true); }); - it("Configure file diagnostics events are generated when the config file doesn't have errors", () => { + it("If config file doesnt have errors, they are not reported", () => { const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -822,13 +907,10 @@ namespace ts.tscWatch { const host = createWatchedSystem([file, configFile, libFile]); createWatchModeWithConfigFile(configFile.path, host); - checkOutputDoesNotContain(host, [ - `a/b/tsconfig.json(3,29): error TS5023: Unknown compiler option \'foo\'.${host.newLine}`, - `a/b/tsconfig.json(4,29): error TS5023: Unknown compiler option \'allowJS\'.${host.newLine}` - ]); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); }); - it("Configure file diagnostics events are generated when the config file changes", () => { + it("Reports errors when the config file changes", () => { const file = { path: "/a/b/app.ts", content: "let x = 10" @@ -841,9 +923,8 @@ namespace ts.tscWatch { }; const host = createWatchedSystem([file, configFile, libFile]); - createWatchModeWithConfigFile(configFile.path, host); - const error = `a/b/tsconfig.json(3,25): error TS5023: Unknown compiler option 'haha'.${host.newLine}`; - checkOutputDoesNotContain(host, [error]); + const watch = createWatchModeWithConfigFile(configFile.path, host); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); configFile.content = `{ "compilerOptions": { @@ -852,15 +933,16 @@ namespace ts.tscWatch { }`; host.reloadFS([file, configFile, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputContains(host, [error]); + checkOutputErrors(host, [ + getUnknownCompilerOption(watch(), configFile, "haha") + ]); - host.clearOutput(); configFile.content = `{ "compilerOptions": {} }`; host.reloadFS([file, configFile, libFile]); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [error]); + checkOutputErrors(host); }); it("non-existing directories listed in config file input array should be tolerated without crashing the server", () => { @@ -935,29 +1017,28 @@ namespace ts.tscWatch { }`; const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment; const configFileContentWithoutCommentLine = configFileContentBeforeComment + configFileContentAfterComment; - - const line = 5; - const errors = (line: number) => [ - `a/b/tsconfig.json(${line},25): error TS5053: Option \'allowJs\' cannot be specified with option \'declaration\'.\n`, - `a/b/tsconfig.json(${line + 1},25): error TS5053: Option \'allowJs\' cannot be specified with option \'declaration\'.\n` - ]; - const configFile = { path: "/a/b/tsconfig.json", content: configFileContentWithComment }; - const host = createWatchedSystem([file, libFile, configFile]); - createWatchModeWithConfigFile(configFile.path, host); - checkOutputContains(host, errors(line)); - checkOutputDoesNotContain(host, errors(line - 2)); - host.clearOutput(); + const files = [file, libFile, configFile]; + const host = createWatchedSystem(files); + const watch = createWatchModeWithConfigFile(configFile.path, host); + const errors = () => [ + getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"), + getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration") + ]; + const intialErrors = errors(); + checkOutputErrors(host, intialErrors, /*isInitial*/ true); configFile.content = configFileContentWithoutCommentLine; - host.reloadFS([file, configFile]); + host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkOutputContains(host, errors(line - 2)); - checkOutputDoesNotContain(host, errors(line)); + const nowErrors = errors(); + checkOutputErrors(host, nowErrors); + assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length); + assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length); }); }); @@ -1485,23 +1566,20 @@ namespace ts.tscWatch { path: "/a/d/f0.ts", content: `import {x} from "f1"` }; - const imported = { path: "/a/f1.ts", content: `foo()` }; - const f1IsNotModule = `a/d/f0.ts(1,17): error TS2306: File '${imported.path}' is not a module.\n`; - const cannotFindFoo = `a/f1.ts(1,1): error TS2304: Cannot find name 'foo'.\n`; - const cannotAssignValue = "a/d/f0.ts(2,21): error TS2322: Type '1' is not assignable to type 'string'.\n"; - const files = [root, imported, libFile]; const host = createWatchedSystem(files); - createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); + const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); + + const f1IsNotModule = getDiagnosticOfFileFromProgram(watch(), root.path, root.content.indexOf('"f1"'), '"f1"'.length, Diagnostics.File_0_is_not_a_module, imported.path); + const cannotFindFoo = getDiagnosticOfFileFromProgram(watch(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo"); // ensure that imported file was found - checkOutputContains(host, [f1IsNotModule, cannotFindFoo]); - host.clearOutput(); + checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*isInitial*/ true); const originalFileExists = host.fileExists; { @@ -1517,8 +1595,11 @@ namespace ts.tscWatch { host.runQueuedTimeoutCallbacks(); // ensure file has correct number of errors after edit - checkOutputContains(host, [f1IsNotModule, cannotAssignValue]); - host.clearOutput(); + checkOutputErrors(host, [ + f1IsNotModule, + getDiagnosticOfFileFromProgram(watch(), root.path, newContent.indexOf("var x") + "var ".length, "x".length, Diagnostics.Type_0_is_not_assignable_to_type_1, 1, "string"), + cannotFindFoo + ]); } { let fileExistsIsCalled = false; @@ -1534,13 +1615,13 @@ namespace ts.tscWatch { root.content = `import {x} from "f2"`; host.reloadFS(files); - // trigger synchronization to make sure that LSHost will try to find 'f2' module on disk - host.runQueuedTimeoutCallbacks(); + // trigger synchronization to make sure that LSHost will try to find 'f2' module on disk + host.runQueuedTimeoutCallbacks(); - // ensure file has correct number of errors after edit - const cannotFindModuleF2 = `a/d/f0.ts(1,17): error TS2307: Cannot find module 'f2'.\n`; - checkOutputContains(host, [cannotFindModuleF2]); - host.clearOutput(); + // ensure file has correct number of errors after edit + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), root, "f2") + ]); assert.isTrue(fileExistsIsCalled); } @@ -1561,7 +1642,7 @@ namespace ts.tscWatch { host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkOutputContains(host, [f1IsNotModule, cannotFindFoo]); + checkOutputErrors(host, [f1IsNotModule, cannotFindFoo]); assert.isTrue(fileExistsCalled); } }); @@ -1593,12 +1674,12 @@ namespace ts.tscWatch { return originalFileExists.call(host, fileName); }; - createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); + const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); - const barNotFound = `a/foo.ts(1,17): error TS2307: Cannot find module 'bar'.\n`; assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); - checkOutputContains(host, [barNotFound]); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), root, "bar") + ], /*isInitial*/ true); fileExistsCalledForBar = false; root.content = `import {y} from "bar"`; @@ -1606,7 +1687,7 @@ namespace ts.tscWatch { host.runQueuedTimeoutCallbacks(); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called."); - checkOutputDoesNotContain(host, [barNotFound]); + checkOutputErrors(host); }); it("should compile correctly when resolved module goes missing and then comes back (module is not part of the root)", () => { @@ -1617,7 +1698,7 @@ namespace ts.tscWatch { const imported = { path: `/a/bar.d.ts`, - content: `export const y = 1;` + content: `export const y = 1;export const x = 10;` }; const files = [root, libFile]; @@ -1635,25 +1716,24 @@ namespace ts.tscWatch { return originalFileExists.call(host, fileName); }; - createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); + const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD }); - const barNotFound = `a/foo.ts(1,17): error TS2307: Cannot find module 'bar'.\n`; assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); - checkOutputDoesNotContain(host, [barNotFound]); - host.clearOutput(); + checkOutputErrors(host, emptyArray, /*isInitial*/ true); fileExistsCalledForBar = false; host.reloadFS(files); host.runQueuedTimeoutCallbacks(); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called."); - checkOutputContains(host, [barNotFound]); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), root, "bar") + ]); fileExistsCalledForBar = false; host.reloadFS(filesWithImported); host.checkTimeoutQueueLengthAndRun(1); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called."); - checkOutputDoesNotContain(host, [barNotFound]); + checkOutputErrors(host); }); it("works when module resolution changes to ambient module", () => { @@ -1677,30 +1757,6 @@ namespace ts.tscWatch { declare module "fs" { export interface Stats { isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atimeMs: number; - mtimeMs: number; - ctimeMs: number; - birthtimeMs: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; } }` }; @@ -1709,15 +1765,15 @@ declare module "fs" { const filesWithNodeType = files.concat(packageJson, nodeType); const host = createWatchedSystem(files, { currentDirectory: "/a/b" }); - createWatchModeWithoutConfigFile([root.path], host, { }); + const watch = createWatchModeWithoutConfigFile([root.path], host, { }); - const fsNotFound = `foo.ts(1,21): error TS2307: Cannot find module 'fs'.\n`; - checkOutputContains(host, [fsNotFound]); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), root, "fs") + ], /*isInitial*/ true); host.reloadFS(filesWithNodeType); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [fsNotFound]); + checkOutputErrors(host); }); it("works when included file with ambient module changes", () => { @@ -1735,17 +1791,6 @@ import * as u from "url"; declare module "url" { export interface Url { href?: string; - protocol?: string; - auth?: string; - hostname?: string; - port?: string; - host?: string; - pathname?: string; - search?: string; - query?: string | any; - slashes?: boolean; - hash?: string; - path?: string; } } ` @@ -1755,30 +1800,6 @@ declare module "url" { declare module "fs" { export interface Stats { isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atimeMs: number; - mtimeMs: number; - ctimeMs: number; - birthtimeMs: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; } } `; @@ -1786,16 +1807,16 @@ declare module "fs" { const files = [root, file, libFile]; const host = createWatchedSystem(files, { currentDirectory: "/a/b" }); - createWatchModeWithoutConfigFile([root.path, file.path], host, {}); + const watch = createWatchModeWithoutConfigFile([root.path, file.path], host, {}); - const fsNotFound = `foo.ts(2,21): error TS2307: Cannot find module 'fs'.\n`; - checkOutputContains(host, [fsNotFound]); - host.clearOutput(); + checkOutputErrors(host, [ + getDiagnosticModuleNotFoundOfFile(watch(), root, "fs") + ], /*isInitial*/ true); file.content += fileContentWithFS; host.reloadFS(files); host.runQueuedTimeoutCallbacks(); - checkOutputDoesNotContain(host, [fsNotFound]); + checkOutputErrors(host); }); }); } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index c16f57235e412..cef70910678ba 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -212,13 +212,13 @@ namespace ts.TestFSWithWatch { directoryName: string; } - export class TestServerHost implements server.ServerHost { + export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost { args: string[] = []; private readonly output: string[] = []; private fs: Map = createMap(); - private getCanonicalFileName: (s: string) => string; + getCanonicalFileName: (s: string) => string; private toPath: (f: string) => Path; private timeoutCallbacks = new Callbacks(); private immediateCallbacks = new Callbacks(); @@ -234,6 +234,10 @@ namespace ts.TestFSWithWatch { this.reloadFS(fileOrFolderList); } + getNewLine() { + return this.newLine; + } + toNormalizedAbsolutePath(s: string) { return getNormalizedAbsolutePath(s, this.currentDirectory); } From cf9b83accc62833a109e48f03463bb1c02a5f767 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 10 Oct 2017 21:15:20 -0700 Subject: [PATCH 115/246] Instead of counting events with name, verify each event to not equal event name --- src/harness/unittests/tsserverProjectSystem.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index d5b9b9d62fcf4..af85e21260aea 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -173,8 +173,7 @@ namespace ts.projectSystem { } hasZeroEvent(eventName: T["eventName"]) { - const eventCount = countWhere(this.events, event => event.eventName === eventName); - assert.equal(eventCount, 0); + this.events.forEach(event => assert.notEqual(event.eventName, eventName)); } checkSingleConfigFileDiagEvent(configFileName: string, triggerFile: string) { From de68f067d5bf1b60aaae6c0162e482480807944e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 08:17:40 -0700 Subject: [PATCH 116/246] Set flags on fresh object types from getSpreadType Previously, getSpreadType didn't set any flags and relied on its callers to do so. This was error-prone because getSpreadType often returns non-fresh types. --- src/compiler/checker.ts | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a61ded007f449..7c62dd4468c1c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7846,7 +7846,7 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type): Type { + function getSpreadType(left: Type, right: Type, symbol: Symbol, propagatedFlags: TypeFlags): Type { if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } @@ -7857,10 +7857,10 @@ namespace ts { return left; } if (left.flags & TypeFlags.Union) { - return mapType(left, t => getSpreadType(t, right)); + return mapType(left, t => getSpreadType(t, right, symbol, propagatedFlags)); } if (right.flags & TypeFlags.Union) { - return mapType(right, t => getSpreadType(left, t)); + return mapType(right, t => getSpreadType(left, t, symbol, propagatedFlags)); } if (right.flags & TypeFlags.NonPrimitive) { return nonPrimitiveType; @@ -7918,7 +7918,13 @@ namespace ts { members.set(leftProp.escapedName, getNonReadonlySymbol(leftProp)); } } - return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); + + const spread = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); + spread.flags |= propagatedFlags; + spread.flags |= TypeFlags.FreshLiteral; + (spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; + spread.symbol = symbol; + return spread; } function getNonReadonlySymbol(prop: Symbol) { @@ -13858,7 +13864,7 @@ namespace ts { checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign); } if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType()); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags); propertiesArray = []; propertiesTable = createSymbolTable(); hasComputedStringProperty = false; @@ -13870,7 +13876,7 @@ namespace ts { error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); return unknownType; } - spread = getSpreadType(spread, type); + spread = getSpreadType(spread, type, node.symbol, propagatedFlags); offset = i + 1; continue; } @@ -13915,17 +13921,8 @@ namespace ts { if (spread !== emptyObjectType) { if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType()); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags); } - // only set the symbol and flags if this is a (fresh) object type - forEachType(spread, t => { - if (t.flags & TypeFlags.Object) { - t.flags |= propagatedFlags; - t.flags |= TypeFlags.FreshLiteral; - (t as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; - t.symbol = node.symbol; - } - }); return spread; } @@ -14045,7 +14042,7 @@ namespace ts { else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesArray.length > 0) { - spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable)); + spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable), openingLikeElement.symbol, /*propagatedFlags*/ 0); attributesArray = []; attributesTable = createSymbolTable(); } @@ -14054,7 +14051,7 @@ namespace ts { hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType); + spread = getSpreadType(spread, exprType, openingLikeElement.symbol, /*propagatedFlags*/ 0); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -14065,7 +14062,7 @@ namespace ts { if (!hasSpreadAnyType) { if (spread !== emptyObjectType) { if (attributesArray.length > 0) { - spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable)); + spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable), openingLikeElement.symbol, /*propagatedFlags*/ 0); } attributesArray = getPropertiesOfType(spread); } From 576bd8c25f8970adf6952787af9546bb387f8240 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Wed, 11 Oct 2017 09:04:51 -0700 Subject: [PATCH 117/246] Ensure Async Modifier is maintained through ES6 Class Conversion (#19092) --- .../refactors/convertFunctionToEs6Class.ts | 14 +++++----- .../convertFunctionToEs6Class_asyncMethods.ts | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/convertFunctionToEs6Class_asyncMethods.ts diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index 110f64d122043..1b02b11678bf4 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -172,7 +172,8 @@ namespace ts.refactor.convertFunctionToES6Class { switch (assignmentBinaryExpression.right.kind) { case SyntaxKind.FunctionExpression: { const functionExpression = assignmentBinaryExpression.right as FunctionExpression; - const method = createMethod(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword)); + const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); copyComments(assignmentBinaryExpression, method); return method; @@ -192,7 +193,8 @@ namespace ts.refactor.convertFunctionToES6Class { const expression = arrowFunctionBody as Expression; bodyBlock = createBlock([createReturn(expression)]); } - const method = createMethod(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword)); + const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); copyComments(assignmentBinaryExpression, method); return method; @@ -243,7 +245,7 @@ namespace ts.refactor.convertFunctionToES6Class { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } - const modifiers = getExportModifierFromSource(precedingNode); + const modifiers = getModifierKindFromSource(precedingNode, SyntaxKind.ExportKeyword); const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place @@ -256,15 +258,15 @@ namespace ts.refactor.convertFunctionToES6Class { memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } - const modifiers = getExportModifierFromSource(node); + const modifiers = getModifierKindFromSource(node, SyntaxKind.ExportKeyword); const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); // Don't call copyComments here because we'll already leave them in place return cls; } - function getExportModifierFromSource(source: Node) { - return filter(source.modifiers, modifier => modifier.kind === SyntaxKind.ExportKeyword); + function getModifierKindFromSource(source: Node, kind: SyntaxKind) { + return filter(source.modifiers, modifier => modifier.kind === kind); } } } \ No newline at end of file diff --git a/tests/cases/fourslash/convertFunctionToEs6Class_asyncMethods.ts b/tests/cases/fourslash/convertFunctionToEs6Class_asyncMethods.ts new file mode 100644 index 0000000000000..ed230d504351d --- /dev/null +++ b/tests/cases/fourslash/convertFunctionToEs6Class_asyncMethods.ts @@ -0,0 +1,27 @@ +/// + +// @allowNonTsExtensions: true +// @Filename: test123.js +////export function /**/MyClass() { +////} +////MyClass.prototype.foo = async function() { +//// await 2; +////} +////MyClass.bar = async function() { +//// await 3; +////} + +verify.applicableRefactorAvailableAtMarker(""); +verify.fileAfterApplyingRefactorAtMarker("", +`export class MyClass { + constructor() { + } + async foo() { + await 2; + } + static async bar() { + await 3; + } +} +`, +'Convert to ES2015 class', 'convert'); From 0c4fe37a92c6aa16fa9746eb828a2c158f5ea3fe Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 11 Oct 2017 10:03:29 -0700 Subject: [PATCH 118/246] In issue template, recommend to use `typescript@next` (#19098) --- issue_template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/issue_template.md b/issue_template.md index e812fe7b74c64..ddc1d070bc992 100644 --- a/issue_template.md +++ b/issue_template.md @@ -2,7 +2,8 @@ -**TypeScript Version:** 2.4.0 / nightly (2.5.0-dev.201xxxxx) + +**TypeScript Version:** 2.6.0-dev.201xxxxx **Code** From e85c6330bad3255189785e676addbfaf26a65aa3 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 11 Oct 2017 10:03:53 -0700 Subject: [PATCH 119/246] Add package-lock.json to repository (#19099) --- .gitignore | 1 - package-lock.json | 5302 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 5302 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore index 9b93436e7f7c4..90b078fc94f69 100644 --- a/.gitignore +++ b/.gitignore @@ -58,5 +58,4 @@ internal/ !tests/baselines/reference/project/nodeModules*/**/* .idea yarn.lock -package-lock.json .parallelperf.* diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000..cde6c1ff73305 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5302 @@ +{ + "name": "typescript", + "version": "2.6.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", + "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", + "dev": true, + "requires": { + "acorn": "5.1.2", + "css": "2.2.1", + "normalize-path": "2.1.1", + "source-map": "0.5.7", + "through2": "2.0.3" + }, + "dependencies": { + "acorn": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "2.1.1", + "through2": "2.0.3" + } + }, + "@types/browserify": { + "version": "12.0.33", + "resolved": "https://registry.npmjs.org/@types/browserify/-/browserify-12.0.33.tgz", + "integrity": "sha512-mY6dYfq1Ns3Xqz/JFUcyoWaXtm0XDoNhkU1vCwM/ULM5zqNL+SbtacJhce/JCgPeCdbqdVqq77tJ4HwdtypSxg==", + "dev": true, + "requires": { + "@types/insert-module-globals": "7.0.0", + "@types/node": "8.0.34" + } + }, + "@types/chai": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.4.tgz", + "integrity": "sha512-cvU0HomQ7/aGDQJZsbtJXqBQ7w4J4TqLB0Z/h8mKrpRjfeZEvTbygkfJEb7fWdmwpIeDeFmIVwAEqS0OYuUv3Q==", + "dev": true + }, + "@types/colors": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/colors/-/colors-1.1.3.tgz", + "integrity": "sha1-VBOwp6GxbdGL4OP9V9L+7Mgcx3Y=", + "dev": true + }, + "@types/convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha512-4OHKJEw70U59CN24TLRxU3W+B/9GPp0P6g+eNIsObZLAIqw6NTEBorkjIpei4xsvUCx+YzFwUtt4MBZbfSLvbQ==", + "dev": true + }, + "@types/del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/del/-/del-3.0.0.tgz", + "integrity": "sha512-18mSs54BvzV8+TTQxt0ancig6tsuPZySnhp3cQkWFFDmDMavU4pmWwR+bHHqRBWODYqpzIzVkqKLuk/fP6yypQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.33" + } + }, + "@types/glob": { + "version": "5.0.33", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.33.tgz", + "integrity": "sha512-BcD4yyWz+qmCggaYMSFF0Xn7GkO6tgwm3Fh9Gxk/kQmEU3Z7flQTnVlMyKBUNvXXNTCCyjqK4XT4/2hLd1gQ2A==", + "dev": true, + "requires": { + "@types/minimatch": "3.0.1", + "@types/node": "8.0.34" + } + }, + "@types/gulp": { + "version": "3.8.33", + "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-3.8.33.tgz", + "integrity": "sha512-3UpA2pkKO40cNPe/8bxMQFWSASR9Jx67JfN9Z2Cf6ogfDMwXgEHm2XjKmuLYEtrp1IHYApOWlYMLYNgtTJgSAw==", + "dev": true, + "requires": { + "@types/node": "8.0.34", + "@types/orchestrator": "0.3.0", + "@types/vinyl": "2.0.1" + } + }, + "@types/gulp-concat": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/@types/gulp-concat/-/gulp-concat-0.0.31.tgz", + "integrity": "sha512-F14zRcKn15HC59RXRlHpcxj79WoLjkJBJBPfN0NBZOgkRCfDZYVu8rs0Y/CH4CJGUbbc/nHczD2LmepDS+ARaA==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/gulp-help": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/gulp-help/-/gulp-help-0.0.33.tgz", + "integrity": "sha1-ZejGUSQQkiVTf6OQA8S6UfT9GsU=", + "dev": true, + "requires": { + "@types/gulp": "3.8.33", + "@types/node": "8.0.34", + "@types/orchestrator": "0.3.0" + } + }, + "@types/gulp-newer": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/gulp-newer/-/gulp-newer-0.0.30.tgz", + "integrity": "sha1-bqn7oVsFdr5CTpl31IlCAEZKFR4=", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/gulp-sourcemaps": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/@types/gulp-sourcemaps/-/gulp-sourcemaps-0.0.31.tgz", + "integrity": "sha512-kJD1byVNx+sdQlaBzZpSGeFH/4l99TXTY4XSGW+aRk27eOnVyk6VknXJpsb1Jk5E4ThKxZ8GYy6ais7MtprK1w==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/insert-module-globals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/insert-module-globals/-/insert-module-globals-7.0.0.tgz", + "integrity": "sha512-zudCJPwluh1VUDB6Gl/OQdRp+fYy3+47huJB/JMQubMS2p+sH18MCVK4WUz3FqaWLB12yh5ELxVR/+tqwlm/qA==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/merge2": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/merge2/-/merge2-1.1.2.tgz", + "integrity": "sha512-Xy54xPmFQ8oAx0S3ku46i/zXE4dvfxl5M8n4p2M62IwxPau8IpobiRtL4jkrUzX6Kgeyb34BHOh0i70SDjKHeA==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/minimatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.1.tgz", + "integrity": "sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, + "@types/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha512-XA4vNO6GCBz8Smq0hqSRo4yRWMqr4FPQrWjhJt6nKskzly4/p87SfuJMFYGRyYb6jo2WNIQU2FDBsY5r1BibUA==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/mocha": { + "version": "2.2.43", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.43.tgz", + "integrity": "sha512-xNlAmH+lRJdUMXClMTI9Y0pRqIojdxfm7DHsIxoB2iTzu3fnPmSMEN8SsSx0cdwV36d02PWCWaDUoZPDSln+xw==", + "dev": true + }, + "@types/node": { + "version": "8.0.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.34.tgz", + "integrity": "sha512-Jnmm57+nHqvJUPwUzt1CLoLzFtF2B2vgG7cWFut+a4nqTp9/L6pL0N+o0Jt3V7AQnCKMsPEqQpLFZYleBCdq3w==", + "dev": true + }, + "@types/orchestrator": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@types/orchestrator/-/orchestrator-0.3.0.tgz", + "integrity": "sha1-v4ShaZyTMNT+ic2BJj6PwJ+zKXg=", + "dev": true, + "requires": { + "@types/node": "8.0.34", + "@types/q": "0.0.37" + }, + "dependencies": { + "@types/q": { + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.37.tgz", + "integrity": "sha512-vjFGX1zMTMz/kUp3xgfJcxMVLkMWVMrdlyc0RwVyve1y9jxwqNaT8wTcv6M51ylq2a/zn5lm8g7qPSoIS4uvZQ==", + "dev": true + } + } + }, + "@types/q": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.0.5.tgz", + "integrity": "sha512-sudQPADzmQjXYS1fS2TxbWA/N/vbbfaO4Y7luPaAEyRWZVXC8jHwKV8KgNDbT7IHQaONNZWy9BYsodxY7IyDXQ==", + "dev": true + }, + "@types/run-sequence": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/run-sequence/-/run-sequence-0.0.29.tgz", + "integrity": "sha1-atD3ODE24TklMi5p/EHbd7MLIHU=", + "dev": true, + "requires": { + "@types/gulp": "3.8.33", + "@types/node": "8.0.34" + } + }, + "@types/through2": { + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.33.tgz", + "integrity": "sha1-H/LoihAN+1sUDnu5h5HxGUQA0TE=", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/vinyl": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.1.tgz", + "integrity": "sha512-Joudabfn2ZofU2usW04y8OLmN75u7ZQkW0MCT3AnoBf5oUBp5iQ3Pgfz9+y1RdWkzhCPZo9/wBJ7FMWW2JrY0g==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "@types/xml2js": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.0.tgz", + "integrity": "sha512-3gw0UqFMq7PsfMDwsawD0/L48soXfzOEh0NSAWVO99IZXnhx9LD3nOldHIpGYzZBsrS9NV2vaRFvEdWe+UweXQ==", + "dev": true, + "requires": { + "@types/node": "8.0.34" + } + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1.js": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", + "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", + "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "combine-source-map": "0.7.2", + "defined": "1.0.0", + "through2": "2.0.3", + "umd": "3.0.1" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserify": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.4.0.tgz", + "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "assert": "1.4.1", + "browser-pack": "6.0.2", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "5.0.8", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.11.1", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "1.0.0", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "labeled-stream-splicer": "2.0.0", + "module-deps": "4.1.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.3", + "resolve": "1.1.7", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "subarg": "1.0.0", + "syntax-error": "1.3.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + } + }, + "browserify-aes": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.8.tgz", + "integrity": "sha512-WYCMOT/PtGTlpOKFht0YJFYcPy6pLCR98CtWfzK13zoynLlBMvAdEMSRGmgnJCw2M2j/5qxBkinZQFobieM8dQ==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.0.8", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", + "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "1.0.7", + "through2": "2.0.3" + } + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + } + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "concat-with-sourcemaps": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", + "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "crypto-browserify": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.31" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.2.1.tgz", + "integrity": "sha512-u0TV6HcfLsZ03xLBhdhSViQMldaiQ2o+8/nSILaXkuNSWvxkx66vYJUAam0Eu7gAilJRX/69J4kKdqajQPaPyw==", + "dev": true, + "requires": { + "debug": "3.1.0", + "memoizee": "0.4.11", + "object-assign": "4.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.3" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.2" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "detective": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", + "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "defined": "1.0.0" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + } + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.31.tgz", + "integrity": "sha1-e7k4yVp/G59ygJLcCcQe3MOY7v4=", + "dev": true, + "requires": { + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.31", + "es6-symbol": "3.1.1" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.31" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.31", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.31" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "filelist": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-0.0.6.tgz", + "integrity": "sha1-WKZBrR9XV0on/oekQO8xiDS1Vxk=", + "dev": true, + "requires": { + "minimatch": "3.0.4", + "utilities": "0.0.37" + }, + "dependencies": { + "utilities": { + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/utilities/-/utilities-0.0.37.tgz", + "integrity": "sha1-o0cNCn9ogULZ6KV87hEo8S4Z4ZY=", + "dev": true + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.3.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.4", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + } + }, + "gulp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-1.0.0.tgz", + "integrity": "sha1-mubGVr2cTzae6AXu9WV4a8gQBbA=", + "dev": true, + "requires": { + "gulp-util": "2.2.20", + "through2": "0.4.2" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + }, + "dependencies": { + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + } + } + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "dev": true, + "requires": { + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" + } + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true, + "requires": { + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "through2": "2.0.3", + "vinyl": "2.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.0.0", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, + "gulp-help": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/gulp-help/-/gulp-help-1.6.1.tgz", + "integrity": "sha1-Jh2xhuGDl/7z9qLCLpwxW/qIrgw=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "object-assign": "3.0.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulp-insert": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/gulp-insert/-/gulp-insert-0.5.0.tgz", + "integrity": "sha1-MjE/E+SiPPWsylzl8MCAkjx3hgI=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "streamqueue": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "gulp-newer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gulp-newer/-/gulp-newer-1.3.0.tgz", + "integrity": "sha1-1Q7Ky7gi7aSStXMkpshaB/2aVcE=", + "dev": true, + "requires": { + "glob": "7.1.2", + "gulp-util": "3.0.8", + "kew": "0.7.0" + } + }, + "gulp-sourcemaps": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz", + "integrity": "sha512-1qHCI3hdmsMdq/SUotxwUh/L8YzlI6J9zQ5ifNOtx4Y6KV5y5sGuORv1KZzWhuKtz/mXNh5xLESUtwC4EndCjA==", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.0.1", + "@gulp-sourcemaps/map-sources": "1.0.0", + "acorn": "4.0.13", + "convert-source-map": "1.5.0", + "css": "2.2.1", + "debug-fabulous": "0.2.1", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.5.7", + "strip-bom-string": "1.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-typescript": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.2.tgz", + "integrity": "sha1-t+Xh08s193LlPmBAJmAYJuK+d/w=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "source-map": "0.5.7", + "through2": "2.0.3", + "vinyl-fs": "2.4.4" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "handlebars": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "combine-source-map": "0.7.2", + "concat-stream": "1.5.2", + "is-buffer": "1.1.5", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.10", + "js-yaml": "3.10.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "jake": { + "version": "8.0.15", + "resolved": "https://registry.npmjs.org/jake/-/jake-8.0.15.tgz", + "integrity": "sha1-8Np9WOeQrBqPhubuDxk+XZIw6rs=", + "dev": true, + "requires": { + "async": "0.9.2", + "chalk": "0.4.0", + "filelist": "0.0.6", + "minimatch": "3.0.4", + "utilities": "1.0.5" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.1.7" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1" + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "requires": { + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "0.10.31" + } + }, + "make-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", + "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "memoizee": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", + "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.31", + "es6-weak-map": "2.0.2", + "event-emitter": "0.3.5", + "is-promise": "2.1.0", + "lru-queue": "0.1.0", + "next-tick": "1.0.0", + "timers-ext": "0.1.2" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "merge2": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.0.tgz", + "integrity": "sha1-D4ghUdmIsfPQdYlFQE+nPuWSPT8=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", + "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "mocha-fivemat-progress-reporter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/mocha-fivemat-progress-reporter/-/mocha-fivemat-progress-reporter-0.1.0.tgz", + "integrity": "sha1-zK/w4ckc9Vf+d+B535lUuRt0d1Y=", + "dev": true + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.5.0", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.3", + "resolve": "1.1.7", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.1", + "browserify-aes": "1.0.8", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", + "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-sequence": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz", + "integrity": "sha512-xW5DmUwdvoyYQUMPKN8UW7TZSFs7AxtT59xo1m5y91jHbvwGlGgOmdV1Yw5P68fkjf3aHUZ4G1o1mZCtNe0qtw==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "gulp-util": "3.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "sander": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", + "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", + "dev": true, + "requires": { + "es6-promise": "3.3.1", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.9" + } + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sorcery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", + "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "minimist": "1.2.0", + "sander": "0.5.1", + "sourcemap-codec": "1.3.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.3.1.tgz", + "integrity": "sha1-mtb5vb1pGTEBbjCTnbyGhnMyMUY=", + "dev": true, + "requires": { + "vlq": "0.2.3" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.3" + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "streamqueue": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/streamqueue/-/streamqueue-0.0.6.tgz", + "integrity": "sha1-ZvX17JTpuK8knkrsLdH3Qb/pTeM=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", + "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "timers-ext": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", + "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", + "dev": true, + "requires": { + "es5-ext": "0.10.31", + "next-tick": "1.0.0" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "travis-fold": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/travis-fold/-/travis-fold-0.1.2.tgz", + "integrity": "sha1-/sAF+dyqJZo/lFnOWmkGq6TFRdo=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "ts-node": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", + "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "chalk": "2.1.0", + "diff": "3.3.1", + "make-error": "1.3.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18", + "tsconfig": "6.0.0", + "v8flags": "3.0.1", + "yn": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "v8flags": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz", + "integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "tsconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", + "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", + "dev": true, + "requires": { + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "tslib": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", + "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==", + "dev": true + }, + "tslint": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.7.0.tgz", + "integrity": "sha1-wl4NDJL6EgHCvDDoROCOaCtPNVI=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "colors": "1.1.2", + "commander": "2.11.0", + "diff": "3.3.1", + "glob": "7.1.2", + "minimatch": "3.0.4", + "resolve": "1.4.0", + "semver": "5.4.1", + "tslib": "1.8.0", + "tsutils": "2.12.1" + }, + "dependencies": { + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.12.1.tgz", + "integrity": "sha1-9Nlc4zkciXHkblTEzw7bCiHdWyQ=", + "dev": true, + "requires": { + "tslib": "1.8.0" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.6.0-dev.20171011", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.0-dev.20171011.tgz", + "integrity": "sha512-il66U8zNRbF875Gq6cP3K/CthG7Dp9PRpu5w5mVHaPcolzJhrdLa3K2WavqqJg/7h7sPOZvsU8nYdXO61sHagg==", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utilities": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utilities/-/utilities-1.0.5.tgz", + "integrity": "sha1-8rd6iPNRBzP8chW1xIalBKdaskU=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": "1.2.4", + "xmlbuilder": "9.0.4" + } + }, + "xmlbuilder": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", + "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + } + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + } + } +} From 142a88a4aeab6d24a179cc0782d6914eb0904f30 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Oct 2017 10:51:46 -0700 Subject: [PATCH 120/246] Update the comment on emit handler method --- src/compiler/builder.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 093c6ec4d03ee..192f1e430278e 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -76,14 +76,13 @@ namespace ts { * For all source files, either "onUpdateSourceFile" or "onUpdateSourceFileWithSameVersion" will be called. * If the builder is sure that the source file needs an update, "onUpdateSourceFile" will be called; * otherwise "onUpdateSourceFileWithSameVersion" will be called. - * This should return whether the source file should be marked as changed (meaning that something associated with file has changed, e.g. module resolution) */ onUpdateSourceFile(program: Program, sourceFile: SourceFile): void; /** * For all source files, either "onUpdateSourceFile" or "onUpdateSourceFileWithSameVersion" will be called. * If the builder is sure that the source file needs an update, "onUpdateSourceFile" will be called; * otherwise "onUpdateSourceFileWithSameVersion" will be called. - * This should return whether the source file should be marked as changed (meaning that something associated with file has changed, e.g. module resolution) + * This function should return whether the source file should be marked as changed (meaning that something associated with file has changed, e.g. module resolution) */ onUpdateSourceFileWithSameVersion(program: Program, sourceFile: SourceFile): boolean; /** From 81fc2a14d19ae763286f75a6fba61e05e777edd3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 12:01:26 -0700 Subject: [PATCH 121/246] Don't check for callbacks in recursive call that resulted from callbacks --- 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 ce1769118a454..0cb7fe909dc4b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8579,16 +8579,16 @@ namespace ts { for (let i = 0; i < checkCount; i++) { const sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source); const targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target); - const sourceSig = getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = getSingleCallSignature(getNonNullableType(targetType)); // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, // they naturally relate only contra-variantly). However, if the source and target parameters both have - // function types with a single call signature, we known we are relating two callback parameters. In + // function types with a single call signature, we know we are relating two callback parameters. In // that case it is sufficient to only relate the parameters of the signatures co-variantly because, // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. + const sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); + const targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType)); const callbacks = sourceSig && targetSig && !sourceSig.typePredicate && !targetSig.typePredicate && (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); const related = callbacks ? From 07e4819b8bb5db64c2d00c91b7ce184de1eb4723 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 12:01:38 -0700 Subject: [PATCH 122/246] Add regression test --- tests/cases/compiler/mutuallyRecursiveCallbacks.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/cases/compiler/mutuallyRecursiveCallbacks.ts diff --git a/tests/cases/compiler/mutuallyRecursiveCallbacks.ts b/tests/cases/compiler/mutuallyRecursiveCallbacks.ts new file mode 100644 index 0000000000000..94f2d28578614 --- /dev/null +++ b/tests/cases/compiler/mutuallyRecursiveCallbacks.ts @@ -0,0 +1,7 @@ +// Repro from #18277 + +interface Foo { (bar: Bar): void }; +type Bar = (foo: Foo) => Foo; +declare function foo(bar: Bar): void; +declare var bar: Bar<{}>; +bar = foo; From 38cec121902d505de3cf71711f7c4c847563e9d6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 12:02:01 -0700 Subject: [PATCH 123/246] Accept new baselines --- .../mutuallyRecursiveCallbacks.errors.txt | 24 +++++++++++++ .../reference/mutuallyRecursiveCallbacks.js | 14 ++++++++ .../mutuallyRecursiveCallbacks.symbols | 34 ++++++++++++++++++ .../mutuallyRecursiveCallbacks.types | 35 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 tests/baselines/reference/mutuallyRecursiveCallbacks.errors.txt create mode 100644 tests/baselines/reference/mutuallyRecursiveCallbacks.js create mode 100644 tests/baselines/reference/mutuallyRecursiveCallbacks.symbols create mode 100644 tests/baselines/reference/mutuallyRecursiveCallbacks.types diff --git a/tests/baselines/reference/mutuallyRecursiveCallbacks.errors.txt b/tests/baselines/reference/mutuallyRecursiveCallbacks.errors.txt new file mode 100644 index 0000000000000..0682caad5b8aa --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveCallbacks.errors.txt @@ -0,0 +1,24 @@ +tests/cases/compiler/mutuallyRecursiveCallbacks.ts(7,1): error TS2322: Type '(bar: Bar) => void' is not assignable to type 'Bar<{}>'. + Types of parameters 'bar' and 'foo' are incompatible. + Types of parameters 'bar' and 'foo' are incompatible. + Type 'Foo<{}>' is not assignable to type 'Bar<{}>'. + Types of parameters 'bar' and 'foo' are incompatible. + Type 'void' is not assignable to type 'Foo<{}>'. + + +==== tests/cases/compiler/mutuallyRecursiveCallbacks.ts (1 errors) ==== + // Repro from #18277 + + interface Foo { (bar: Bar): void }; + type Bar = (foo: Foo) => Foo; + declare function foo(bar: Bar): void; + declare var bar: Bar<{}>; + bar = foo; + ~~~ +!!! error TS2322: Type '(bar: Bar) => void' is not assignable to type 'Bar<{}>'. +!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible. +!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible. +!!! error TS2322: Type 'Foo<{}>' is not assignable to type 'Bar<{}>'. +!!! error TS2322: Types of parameters 'bar' and 'foo' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'Foo<{}>'. + \ No newline at end of file diff --git a/tests/baselines/reference/mutuallyRecursiveCallbacks.js b/tests/baselines/reference/mutuallyRecursiveCallbacks.js new file mode 100644 index 0000000000000..df52508df7a17 --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveCallbacks.js @@ -0,0 +1,14 @@ +//// [mutuallyRecursiveCallbacks.ts] +// Repro from #18277 + +interface Foo { (bar: Bar): void }; +type Bar = (foo: Foo) => Foo; +declare function foo(bar: Bar): void; +declare var bar: Bar<{}>; +bar = foo; + + +//// [mutuallyRecursiveCallbacks.js] +// Repro from #18277 +; +bar = foo; diff --git a/tests/baselines/reference/mutuallyRecursiveCallbacks.symbols b/tests/baselines/reference/mutuallyRecursiveCallbacks.symbols new file mode 100644 index 0000000000000..50cb0c0dea052 --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveCallbacks.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts === +// Repro from #18277 + +interface Foo { (bar: Bar): void }; +>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14)) +>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 20)) +>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 2, 14)) + +type Bar = (foo: Foo) => Foo; +>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9)) +>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 15)) +>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9)) +>Foo : Symbol(Foo, Decl(mutuallyRecursiveCallbacks.ts, 0, 0)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 3, 9)) + +declare function foo(bar: Bar): void; +>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21)) +>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 4, 24)) +>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41)) +>T : Symbol(T, Decl(mutuallyRecursiveCallbacks.ts, 4, 21)) + +declare var bar: Bar<{}>; +>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11)) +>Bar : Symbol(Bar, Decl(mutuallyRecursiveCallbacks.ts, 2, 41)) + +bar = foo; +>bar : Symbol(bar, Decl(mutuallyRecursiveCallbacks.ts, 5, 11)) +>foo : Symbol(foo, Decl(mutuallyRecursiveCallbacks.ts, 3, 38)) + diff --git a/tests/baselines/reference/mutuallyRecursiveCallbacks.types b/tests/baselines/reference/mutuallyRecursiveCallbacks.types new file mode 100644 index 0000000000000..4a7b4dd049314 --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveCallbacks.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/mutuallyRecursiveCallbacks.ts === +// Repro from #18277 + +interface Foo { (bar: Bar): void }; +>Foo : Foo +>T : T +>bar : Bar +>Bar : Bar +>T : T + +type Bar = (foo: Foo) => Foo; +>Bar : Bar +>T : T +>foo : Foo +>Foo : Foo +>T : T +>Foo : Foo +>T : T + +declare function foo(bar: Bar): void; +>foo : (bar: Bar) => void +>T : T +>bar : Bar +>Bar : Bar +>T : T + +declare var bar: Bar<{}>; +>bar : Bar<{}> +>Bar : Bar + +bar = foo; +>bar = foo : (bar: Bar) => void +>bar : Bar<{}> +>foo : (bar: Bar) => void + From 26290a88ac8daa7bcc4e12f077d2184cd99e0cd3 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 11 Oct 2017 12:07:16 -0700 Subject: [PATCH 124/246] Updated error baseline --- tests/baselines/reference/genericDefaultsErrors.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/genericDefaultsErrors.errors.txt b/tests/baselines/reference/genericDefaultsErrors.errors.txt index 762bb92535b5c..b1afd6f173b74 100644 --- a/tests/baselines/reference/genericDefaultsErrors.errors.txt +++ b/tests/baselines/reference/genericDefaultsErrors.errors.txt @@ -21,7 +21,7 @@ tests/cases/compiler/genericDefaultsErrors.ts(33,15): error TS2707: Generic type tests/cases/compiler/genericDefaultsErrors.ts(36,15): error TS2707: Generic type 'i09' requires between 2 and 3 type arguments. tests/cases/compiler/genericDefaultsErrors.ts(38,20): error TS2304: Cannot find name 'T'. tests/cases/compiler/genericDefaultsErrors.ts(38,20): error TS4033: Property 'x' of exported interface has or is using private name 'T'. -tests/cases/compiler/genericDefaultsErrors.ts(42,29): error TS2715: Type parameter 'T' has a circular default. +tests/cases/compiler/genericDefaultsErrors.ts(42,29): error TS2716: Type parameter 'T' has a circular default. ==== tests/cases/compiler/genericDefaultsErrors.ts (22 errors) ==== @@ -112,4 +112,4 @@ tests/cases/compiler/genericDefaultsErrors.ts(42,29): error TS2715: Type paramet // https://github.com/Microsoft/TypeScript/issues/16221 interface SelfReference {} ~~~~~~~~~~~~~ -!!! error TS2715: Type parameter 'T' has a circular default. \ No newline at end of file +!!! error TS2716: Type parameter 'T' has a circular default. \ No newline at end of file From 4930cad653443ec228e2fba8b9e4ba5d0c9c4fdf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 13:33:31 -0700 Subject: [PATCH 125/246] Convert all JSDoc parameters and return types of functions --- src/compiler/diagnosticMessages.json | 2 +- .../refactors/annotateWithTypeFromJSDoc.ts | 113 +++++++++--------- .../refactors/convertFunctionToEs6Class.ts | 2 +- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ab90d47f2a414..99b45639cac94 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3738,7 +3738,7 @@ "category": "Message", "code": 95007 }, - "Annotate with return type from JSDoc": { + "Annotate with types from JSDoc": { "category": "Message", "code": 95008 } diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 3111c0d3ed901..529793b7cd1cb 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -5,13 +5,13 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const annotateTypeFromJSDoc: Refactor = { name: "Annotate with type from JSDoc", description: Diagnostics.Annotate_with_type_from_JSDoc.message, - getEditsForAction, + getEditsForAction: getEditsForAnnotation, getAvailableActions }; - const annotateReturnTypeFromJSDoc: Refactor = { - name: "Annotate with return type from JSDoc", - description: Diagnostics.Annotate_with_return_type_from_JSDoc.message, - getEditsForAction, + const annotateFunctionFromJSDoc: Refactor = { + name: "Annotate with types from JSDoc", + description: Diagnostics.Annotate_with_types_from_JSDoc.message, + getEditsForAction: getEditsForFunctionAnnotation, getAvailableActions }; @@ -23,7 +23,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { | PropertyDeclaration; registerRefactor(annotateTypeFromJSDoc); - registerRefactor(annotateReturnTypeFromJSDoc); + registerRefactor(annotateFunctionFromJSDoc); function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { if (isInJavaScriptFile(context.file)) { @@ -33,8 +33,10 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(node, isTypedNode); if (decl && !decl.type) { - const annotate = getJSDocType(decl) ? annotateTypeFromJSDoc : - getJSDocReturnType(decl) ? annotateReturnTypeFromJSDoc : + const type = getJSDocType(decl); + const returnType = getJSDocReturnType(decl); + const annotate = (returnType || type && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : + type ? annotateTypeFromJSDoc : undefined; if (annotate) { return [{ @@ -51,16 +53,14 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } } - function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined { - // Somehow wrong action got invoked? + function getEditsForAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { if (actionName !== action) { Debug.fail(`actionName !== action: ${actionName} !== ${action}`); return undefined; } - const start = context.startPosition; const sourceFile = context.file; - const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); + const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(token, isTypedNode); const jsdocType = getJSDocReturnType(decl) || getJSDocType(decl); if (!decl || !jsdocType || decl.type) { @@ -69,19 +69,25 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } const changeTracker = textChanges.ChangeTracker.fromContext(context); - if (isParameterOfSimpleArrowFunction(decl)) { - // `x => x` becomes `(x: number) => x`, but in order to make the changeTracker generate the parentheses, - // we have to replace the entire function; it doesn't check that the node it's replacing might require - // other syntax changes - const arrow = decl.parent as ArrowFunction; - const param = decl as ParameterDeclaration; - const replacementParam = createParameter(param.decorators, param.modifiers, param.dotDotDotToken, param.name, param.questionToken, transformJSDocType(jsdocType) as TypeNode, param.initializer); - const replacement = createArrowFunction(arrow.modifiers, arrow.typeParameters, [replacementParam], arrow.type, arrow.equalsGreaterThanToken, arrow.body); - changeTracker.replaceRange(sourceFile, { pos: arrow.getStart(), end: arrow.end }, replacement); - } - else { - changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, replaceType(decl, transformJSDocType(jsdocType) as TypeNode)); + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, addType(decl, transformJSDocType(jsdocType) as TypeNode)); + return { + edits: changeTracker.getChanges(), + renameFilename: undefined, + renameLocation: undefined + }; + } + + function getEditsForFunctionAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { + if (actionName !== action) { + Debug.fail(`actionName !== action: ${actionName} !== ${action}`); + return undefined; } + + const sourceFile = context.file; + const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); + const decl = findAncestor(token, isFunctionLikeDeclaration); + const changeTracker = textChanges.ChangeTracker.fromContext(context); + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, addTypesToFunctionLike(decl)); return { edits: changeTracker.getChanges(), renameFilename: undefined, @@ -97,53 +103,44 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { node.kind === SyntaxKind.PropertyDeclaration; } - function replaceType(decl: DeclarationWithType, jsdocType: TypeNode) { + function addTypesToFunctionLike(decl: FunctionLikeDeclaration) { + const returnType = decl.type || transformJSDocType(getJSDocReturnType(decl)) as TypeNode; + const parameters = decl.parameters.map( + p => createParameter(p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || transformJSDocType(getJSDocType(p)) as TypeNode, p.initializer)); + switch (decl.kind) { + case SyntaxKind.FunctionDeclaration: + return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, parameters, returnType, decl.body); + case SyntaxKind.Constructor: + return createConstructor(decl.decorators, decl.modifiers, parameters, decl.body); + case SyntaxKind.FunctionExpression: + return createFunctionExpression(decl.modifiers, decl.asteriskToken, (decl as FunctionExpression).name, decl.typeParameters, parameters, returnType, decl.body); + case SyntaxKind.ArrowFunction: + return createArrowFunction(decl.modifiers, decl.typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body); + case SyntaxKind.MethodDeclaration: + return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, parameters, returnType, decl.body); + case SyntaxKind.GetAccessor: + return createGetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, returnType, decl.body); + case SyntaxKind.SetAccessor: + return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body); + default: + return Debug.fail(`Unexpected SyntaxKind: ${(decl as any).kind}`); + } + } + + function addType(decl: DeclarationWithType, jsdocType: TypeNode) { switch (decl.kind) { case SyntaxKind.VariableDeclaration: return createVariableDeclaration(decl.name, jsdocType, decl.initializer); - case SyntaxKind.Parameter: - return createParameter(decl.decorators, decl.modifiers, decl.dotDotDotToken, decl.name, decl.questionToken, jsdocType, decl.initializer); case SyntaxKind.PropertySignature: return createPropertySignature(decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); case SyntaxKind.PropertyDeclaration: return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); - case SyntaxKind.FunctionDeclaration: - return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocType, decl.body); - case SyntaxKind.FunctionExpression: - return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, decl.parameters, jsdocType, decl.body); - case SyntaxKind.ArrowFunction: - return createArrowFunction(decl.modifiers, decl.typeParameters, decl.parameters, jsdocType, decl.equalsGreaterThanToken, decl.body); - case SyntaxKind.MethodDeclaration: - return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, decl.parameters, jsdocType, decl.body); - case SyntaxKind.GetAccessor: - return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, jsdocType, decl.body); default: Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`); return undefined; } } - function isParameterOfSimpleArrowFunction(decl: DeclarationWithType) { - return decl.kind === SyntaxKind.Parameter && decl.parent.kind === SyntaxKind.ArrowFunction && isSimpleArrowFunction(decl.parent); - } - - function isSimpleArrowFunction(parentNode: FunctionTypeNode | ArrowFunction | JSDocFunctionType) { - const parameter = singleOrUndefined(parentNode.parameters); - return parameter - && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter - && !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation - && !some(parentNode.decorators) // parent may not have decorators - && !some(parentNode.modifiers) // parent may not have modifiers - && !some(parentNode.typeParameters) // parent may not have type parameters - && !some(parameter.decorators) // parameter may not have decorators - && !some(parameter.modifiers) // parameter may not have modifiers - && !parameter.dotDotDotToken // parameter may not be rest - && !parameter.questionToken // parameter may not be optional - && !parameter.type // parameter may not have a type annotation - && !parameter.initializer // parameter may not have an initializer - && isIdentifier(parameter.name); // parameter name must be identifier - } - function transformJSDocType(node: Node): Node | undefined { if (node === undefined) { return undefined; diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index e4cd1a420832c..6634dd6121ad8 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -261,4 +261,4 @@ namespace ts.refactor.convertFunctionToES6Class { return cls; } } -} \ No newline at end of file +} From 1a1c1f9e93a6383192aca0a94d10d6d5ce9334b3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 13:34:16 -0700 Subject: [PATCH 126/246] Add and update jsdoc annotation refactoring tests --- .../fourslash/annotateWithTypeFromJSDoc10.ts | 2 +- .../fourslash/annotateWithTypeFromJSDoc11.ts | 2 +- .../fourslash/annotateWithTypeFromJSDoc12.ts | 2 +- .../fourslash/annotateWithTypeFromJSDoc13.ts | 2 +- .../fourslash/annotateWithTypeFromJSDoc14.ts | 2 +- .../fourslash/annotateWithTypeFromJSDoc15.ts | 130 +----------------- .../fourslash/annotateWithTypeFromJSDoc16.ts | 4 +- .../fourslash/annotateWithTypeFromJSDoc17.ts | 18 +++ .../fourslash/annotateWithTypeFromJSDoc18.ts | 11 ++ .../fourslash/annotateWithTypeFromJSDoc3.ts | 34 +---- .../fourslash/annotateWithTypeFromJSDoc4.ts | 88 +----------- .../fourslash/annotateWithTypeFromJSDoc7.ts | 4 +- .../fourslash/annotateWithTypeFromJSDoc8.ts | 4 +- .../fourslash/annotateWithTypeFromJSDoc9.ts | 2 +- 14 files changed, 47 insertions(+), 258 deletions(-) create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts index 88b565fa9328a..0553a411c2e6f 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x): number => x`, 'Annotate with return type from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts index 63b2d85fbfe89..aaa7aaefa5b7e 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('2', * @param {?} x * @returns {number} */ -var f = (x: any) => x`, 'Annotate with type from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts index 95fa0b55cd292..c3c1aad5a90ef 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts @@ -18,4 +18,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', */ m(x): any[] { } -}`, 'Annotate with return type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts index caa3315b87fb2..a47c090cd17e9 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `class C { /** @return {number} */ get c(): number { return 12; } -}`, 'Annotate with return type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts index 43ac95a1c4a52..13b4591de4764 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `/** @return {number} */ function f(): number { return 12; -}`, 'Annotate with return type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts index 487b456d561f4..c316430b71803 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts @@ -13,134 +13,6 @@ //// */ ////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta, /*8*/epsilon, /*9*/zeta) { ////} -verify.applicableRefactorAvailableAtMarker('1'); -verify.fileAfterApplyingRefactorAtMarker('1', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y, z, alpha, beta, gamma, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('2'); -verify.fileAfterApplyingRefactorAtMarker('2', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z, alpha, beta, gamma, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('3'); -verify.fileAfterApplyingRefactorAtMarker('3', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha, beta, gamma, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('4'); -verify.fileAfterApplyingRefactorAtMarker('4', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha: object, beta, gamma, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('5'); -verify.fileAfterApplyingRefactorAtMarker('5', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('6'); -verify.fileAfterApplyingRefactorAtMarker('6', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('7'); -verify.fileAfterApplyingRefactorAtMarker('7', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('8'); -verify.fileAfterApplyingRefactorAtMarker('8', -`/** - * @param {Boolean} x - * @param {String} y - * @param {Number} z - * @param {Object} alpha - * @param {date} beta - * @param {promise} gamma - * @param {array} delta - * @param {Array} epsilon - * @param {promise} zeta - */ -function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - verify.applicableRefactorAvailableAtMarker('9'); verify.fileAfterApplyingRefactorAtMarker('9', `/** @@ -155,4 +27,4 @@ verify.fileAfterApplyingRefactorAtMarker('9', * @param {promise} zeta */ function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta: Promise) { -}`, 'Annotate with type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts index 2f5ab2bcc72ee..a332a84d9109d 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts @@ -1,9 +1,9 @@ /// // @strict: true /////** @type {function(*, ...number, ...boolean): void} */ -////var /*1*/x; +////var /*1*/x = (x, ys, ...zs) => { }; verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `/** @type {function(*, ...number, ...boolean): void} */ -var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void;`, 'Annotate with type from JSDoc', 'annotate'); +var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { };`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts new file mode 100644 index 0000000000000..ed3180d3bd8be --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts @@ -0,0 +1,18 @@ +/// +////class C { +//// /** +//// * @param {number} x - the first parameter +//// */ +//// constructor(/*1*/x) { +//// } +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`class C { + /** + * @param {number} x - the first parameter + */ + constructor(x: number) { + } +}`, 'Annotate with types from JSDoc', 'annotate'); + diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts new file mode 100644 index 0000000000000..9cfcb5c2471f4 --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts @@ -0,0 +1,11 @@ +/// +////class C { +//// /** @param {number} value */ +//// set c(/*1*/value) { return 12 } +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`class C { + /** @param {number} value */ + set c(value: number) { return 12; } +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts index 985b89ed70901..ca5dbe312e3a0 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts @@ -9,37 +9,10 @@ ////function f(/*1*/x, /*2*/y, /*3*/z: string, /*4*/alpha, /*5*/beta) { ////} -verify.applicableRefactorAvailableAtMarker('1'); -verify.fileAfterApplyingRefactorAtMarker('1', -`/** - * @param {number} x - the first parameter - * @param {{ a: string, b: Date }} y - the most complex parameter - * @param z - the best parameter - * @param alpha - the other best parameter - * @param {*} beta - I have no idea how this got here - */ -function f(x: number, y, z: string, alpha, beta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('2'); -verify.fileAfterApplyingRefactorAtMarker('2', -`/** - * @param {number} x - the first parameter - * @param {{ a: string, b: Date }} y - the most complex parameter - * @param z - the best parameter - * @param alpha - the other best parameter - * @param {*} beta - I have no idea how this got here - */ -function f(x: number, y: { - a: string; - b: Date; -}, z: string, alpha, beta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - verify.not.applicableRefactorAvailableAtMarker('3'); verify.not.applicableRefactorAvailableAtMarker('4'); -verify.applicableRefactorAvailableAtMarker('5'); -verify.fileAfterApplyingRefactorAtMarker('5', +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', `/** * @param {number} x - the first parameter * @param {{ a: string, b: Date }} y - the most complex parameter @@ -51,4 +24,5 @@ function f(x: number, y: { a: string; b: Date; }, z: string, alpha, beta: any) { -}`, 'Annotate with type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); + diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts index d4d5384b19c34..2a2d7f943e2e3 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts @@ -12,94 +12,8 @@ ////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta) { ////} -verify.applicableRefactorAvailableAtMarker('1'); -verify.fileAfterApplyingRefactorAtMarker('1', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y, z, alpha, beta, gamma, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('2'); -verify.fileAfterApplyingRefactorAtMarker('2', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y: any, z, alpha, beta, gamma, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('3'); -verify.fileAfterApplyingRefactorAtMarker('3', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y: any, z: number | undefined, alpha, beta, gamma, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); -verify.applicableRefactorAvailableAtMarker('4'); -verify.fileAfterApplyingRefactorAtMarker('4', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y: any, z: number | undefined, alpha: number[], beta, gamma, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - verify.applicableRefactorAvailableAtMarker('5'); verify.fileAfterApplyingRefactorAtMarker('5', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { - a: string; -}, arg1: string, arg2: number) => boolean, gamma, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); -verify.applicableRefactorAvailableAtMarker('6'); -verify.fileAfterApplyingRefactorAtMarker('6', -`/** - * @param {*} x - * @param {?} y - * @param {number=} z - * @param {...number} alpha - * @param {function(this:{ a: string}, string, number): boolean} beta - * @param {number?} gamma - * @param {number!} delta - */ -function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { - a: string; -}, arg1: string, arg2: number) => boolean, gamma: number | null, delta) { -}`, 'Annotate with type from JSDoc', 'annotate'); - -verify.applicableRefactorAvailableAtMarker('7'); -verify.fileAfterApplyingRefactorAtMarker('7', `/** * @param {*} x * @param {?} y @@ -112,4 +26,4 @@ verify.fileAfterApplyingRefactorAtMarker('7', function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { -}`, 'Annotate with type from JSDoc', 'annotate'); +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts index c78f8949b18ce..a99ea8233894d 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts @@ -13,5 +13,5 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {number} x * @returns {number} */ -function f(x): number { -}`, 'Annotate with return type from JSDoc', 'annotate'); +function f(x: number): number { +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts index 502b945819ccc..72ddb36988e0a 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts @@ -13,5 +13,5 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {number} x * @returns {number} */ -var f = function(x): number { -}`, 'Annotate with return type from JSDoc', 'annotate'); +var f = function(x: number): number { +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts index cf2581f5d8f97..6b967e8e004ac 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x: any) => x`, 'Annotate with type from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); From deed981715dcce5d10b3cbfa1701794672212be3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Oct 2017 12:27:21 -0700 Subject: [PATCH 127/246] Handle case sensitivity when looking up config file for Script info Fixes #17726 --- .../unittests/tsserverProjectSystem.ts | 46 +++++++++++++++++++ src/server/editorServices.ts | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 2d761ae33c2f4..f7d082128cdf1 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2917,6 +2917,52 @@ namespace ts.projectSystem { function checkSnapLength(snap: IScriptSnapshot, expectedLength: number) { assert.equal(snap.getLength(), expectedLength, "Incorrect snapshot size"); } + + function verifyOpenFileWorks(useCaseSensitiveFileNames: boolean) { + const file1: FileOrFolder = { + path: "/a/b/src/app.ts", + content: "let x = 10;" + }; + const file2: FileOrFolder = { + path: "/a/B/lib/module2.ts", + content: "let z = 10;" + }; + const configFile: FileOrFolder = { + path: "/a/b/tsconfig.json", + content: "" + }; + const configFile2: FileOrFolder = { + path: "/a/tsconfig.json", + content: "" + }; + const host = createServerHost([file1, file2, configFile, configFile2], { + useCaseSensitiveFileNames + }); + const service = createProjectService(host); + + // Open file1 -> configFile + verifyConfigFileName(file1, "/a", configFile); + verifyConfigFileName(file1, "/a/b", configFile); + verifyConfigFileName(file1, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); + + // Open file2 use root "/a/b" + verifyConfigFileName(file2, "/a", useCaseSensitiveFileNames ? configFile2 : configFile); + verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? undefined : configFile); + verifyConfigFileName(file2, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); + + function verifyConfigFileName(file: FileOrFolder, projectRoot: string, expectedConfigFile: FileOrFolder | undefined) { + const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot); + assert.equal(configFileName, expectedConfigFile && expectedConfigFile.path); + service.closeClientFile(file.path); + } + } + it("works when project root is used with case-sensitive system", () => { + verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ true); + }); + + it("works when project root is used with case-insensitive system", () => { + verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ false); + }); }); describe("Language service", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 173fd86afe4ae..379a5fbfe7e59 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1218,7 +1218,7 @@ namespace ts.server { projectRootPath?: NormalizedPath) { let searchPath = asNormalizedPath(getDirectoryPath(info.fileName)); - while (!projectRootPath || stringContains(searchPath, projectRootPath)) { + while (!projectRootPath || containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames)) { const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName); const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); let result = action(tsconfigFileName, combinePaths(canonicalSearchPath, "tsconfig.json")); From 7e1dd66c19d01fea072ab32a16a8d7354cae247d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 11 Oct 2017 13:44:07 -0700 Subject: [PATCH 128/246] Update to use `help wanted` instead of `Accepting PRs` (#19105) --- pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pull_request_template.md b/pull_request_template.md index 683e6acbf893b..2c49c84641b57 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -3,7 +3,7 @@ Thank you for submitting a pull request! Here's a checklist you might find useful. [ ] There is an associated issue that is labelled - 'Bug' or 'Accepting PRs' or is in the Community milestone + 'Bug' or 'help wanted' or is in the Community milestone [ ] Code is up-to-date with the `master` branch [ ] You've successfully run `jake runtests` locally [ ] You've signed the CLA From 3fef16008d2c29951476321144763b0ce9d5a777 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 14:01:25 -0700 Subject: [PATCH 129/246] Fill missing type arguments during error reporting Previously, only the success path did this; it was missing in the error reporting path in resolveCall. This resulted in crashes for unsupplied type arguments when the supplied type arguments were incorrect. --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36ee2a00eb9cf..56835e13dde4e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16203,8 +16203,10 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { + const isJavascript = isInJavaScriptFile(candidateForTypeArgumentError.declaration); const typeArguments = (node).typeArguments; - checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNode), /*reportErrors*/ true, fallbackError); + const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidateForTypeArgumentError.typeParameters, getMinTypeArgumentCount(candidateForTypeArgumentError.typeParameters), isJavascript); + checkTypeArguments(candidateForTypeArgumentError, typeArguments, typeArgumentTypes, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { let min = Number.POSITIVE_INFINITY; From 156e7e206969b63247944e420a0b6abda970c925 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 14:02:20 -0700 Subject: [PATCH 130/246] Test:Incorrect number of type args during err reporting --- ...peArgumentsDuringErrorReporting.errors.txt | 28 ++++++++ ...mberOfTypeArgumentsDuringErrorReporting.js | 30 ++++++++ ...fTypeArgumentsDuringErrorReporting.symbols | 60 ++++++++++++++++ ...rOfTypeArgumentsDuringErrorReporting.types | 68 +++++++++++++++++++ ...mberOfTypeArgumentsDuringErrorReporting.ts | 21 ++++++ 5 files changed, 207 insertions(+) create mode 100644 tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.errors.txt create mode 100644 tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.js create mode 100644 tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.symbols create mode 100644 tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.types create mode 100644 tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts diff --git a/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.errors.txt b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.errors.txt new file mode 100644 index 0000000000000..41aadb4d465a1 --- /dev/null +++ b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.errors.txt @@ -0,0 +1,28 @@ +tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts(18,4): error TS2559: Type 'MyObjA' has no properties in common with type 'ObjA'. + + +==== tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts (1 errors) ==== + interface ObjA { + y?:string, + } + + interface ObjB {[key:string]:any} + + interface Opts {a:A, b:B} + + const fn = < + A extends ObjA, + B extends ObjB = ObjB + >(opts:Opts):string => 'Z' + + interface MyObjA { + x:string, + } + + fn({ + ~~~~~~ +!!! error TS2559: Type 'MyObjA' has no properties in common with type 'ObjA'. + a: {x: 'X', y: 'Y'}, + b: {}, + }) + \ No newline at end of file diff --git a/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.js b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.js new file mode 100644 index 0000000000000..d74360e8edc05 --- /dev/null +++ b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.js @@ -0,0 +1,30 @@ +//// [incorrectNumberOfTypeArgumentsDuringErrorReporting.ts] +interface ObjA { + y?:string, +} + +interface ObjB {[key:string]:any} + +interface Opts {a:A, b:B} + +const fn = < + A extends ObjA, + B extends ObjB = ObjB +>(opts:Opts):string => 'Z' + +interface MyObjA { + x:string, +} + +fn({ + a: {x: 'X', y: 'Y'}, + b: {}, +}) + + +//// [incorrectNumberOfTypeArgumentsDuringErrorReporting.js] +var fn = function (opts) { return 'Z'; }; +fn({ + a: { x: 'X', y: 'Y' }, + b: {} +}); diff --git a/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.symbols b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.symbols new file mode 100644 index 0000000000000..5f94ad312c0e3 --- /dev/null +++ b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.symbols @@ -0,0 +1,60 @@ +=== tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts === +interface ObjA { +>ObjA : Symbol(ObjA, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 0, 0)) + + y?:string, +>y : Symbol(ObjA.y, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 0, 16)) +} + +interface ObjB {[key:string]:any} +>ObjB : Symbol(ObjB, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 2, 1)) +>key : Symbol(key, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 4, 17)) + +interface Opts {a:A, b:B} +>Opts : Symbol(Opts, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 4, 33)) +>A : Symbol(A, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 15)) +>B : Symbol(B, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 17)) +>a : Symbol(Opts.a, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 22)) +>A : Symbol(A, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 15)) +>b : Symbol(Opts.b, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 26)) +>B : Symbol(B, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 6, 17)) + +const fn = < +>fn : Symbol(fn, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 8, 5)) + + A extends ObjA, +>A : Symbol(A, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 8, 12)) +>ObjA : Symbol(ObjA, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 0, 0)) + + B extends ObjB = ObjB +>B : Symbol(B, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 9, 17)) +>ObjB : Symbol(ObjB, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 2, 1)) +>ObjB : Symbol(ObjB, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 2, 1)) + +>(opts:Opts):string => 'Z' +>opts : Symbol(opts, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 11, 2)) +>Opts : Symbol(Opts, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 4, 33)) +>A : Symbol(A, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 8, 12)) +>B : Symbol(B, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 9, 17)) + +interface MyObjA { +>MyObjA : Symbol(MyObjA, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 11, 32)) + + x:string, +>x : Symbol(MyObjA.x, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 13, 18)) +} + +fn({ +>fn : Symbol(fn, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 8, 5)) +>MyObjA : Symbol(MyObjA, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 11, 32)) + + a: {x: 'X', y: 'Y'}, +>a : Symbol(a, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 17, 12)) +>x : Symbol(x, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 18, 6)) +>y : Symbol(y, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 18, 13)) + + b: {}, +>b : Symbol(b, Decl(incorrectNumberOfTypeArgumentsDuringErrorReporting.ts, 18, 22)) + +}) + diff --git a/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.types b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.types new file mode 100644 index 0000000000000..681a05eba0939 --- /dev/null +++ b/tests/baselines/reference/incorrectNumberOfTypeArgumentsDuringErrorReporting.types @@ -0,0 +1,68 @@ +=== tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts === +interface ObjA { +>ObjA : ObjA + + y?:string, +>y : string +} + +interface ObjB {[key:string]:any} +>ObjB : ObjB +>key : string + +interface Opts {a:A, b:B} +>Opts : Opts +>A : A +>B : B +>a : A +>A : A +>b : B +>B : B + +const fn = < +>fn : (opts: Opts) => string +>< A extends ObjA, B extends ObjB = ObjB>(opts:Opts):string => 'Z' : (opts: Opts) => string + + A extends ObjA, +>A : A +>ObjA : ObjA + + B extends ObjB = ObjB +>B : B +>ObjB : ObjB +>ObjB : ObjB + +>(opts:Opts):string => 'Z' +>opts : Opts +>Opts : Opts +>A : A +>B : B +>'Z' : "Z" + +interface MyObjA { +>MyObjA : MyObjA + + x:string, +>x : string +} + +fn({ +>fn({ a: {x: 'X', y: 'Y'}, b: {},}) : any +>fn : (opts: Opts) => string +>MyObjA : MyObjA +>{ a: {x: 'X', y: 'Y'}, b: {},} : { a: { x: string; y: string; }; b: {}; } + + a: {x: 'X', y: 'Y'}, +>a : { x: string; y: string; } +>{x: 'X', y: 'Y'} : { x: string; y: string; } +>x : string +>'X' : "X" +>y : string +>'Y' : "Y" + + b: {}, +>b : {} +>{} : {} + +}) + diff --git a/tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts b/tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts new file mode 100644 index 0000000000000..2f6c8c7125030 --- /dev/null +++ b/tests/cases/compiler/incorrectNumberOfTypeArgumentsDuringErrorReporting.ts @@ -0,0 +1,21 @@ +interface ObjA { + y?:string, +} + +interface ObjB {[key:string]:any} + +interface Opts {a:A, b:B} + +const fn = < + A extends ObjA, + B extends ObjB = ObjB +>(opts:Opts):string => 'Z' + +interface MyObjA { + x:string, +} + +fn({ + a: {x: 'X', y: 'Y'}, + b: {}, +}) From 917ae32937053026f2c5421a4c2fa6256d31c10f Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 11 Oct 2017 14:50:45 -0700 Subject: [PATCH 131/246] Always log output of execSync (#19110) * Always log output of execSync * Fix lint --- .../typingsInstaller/nodeTypingsInstaller.ts | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index f5d9b866376a0..98478c2d5fc39 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -68,10 +68,14 @@ namespace ts.server.typingsInstaller { return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${TypesRegistryPackageName}/index.json`); } - type ExecSync = (command: string, options: { cwd: string, stdio?: "ignore" }) => any; + interface ExecSyncOptions { + cwd: string; + encoding: "utf-8"; + } + type ExecSync = (command: string, options: ExecSyncOptions) => string; export class NodeTypingsInstaller extends TypingsInstaller { - private readonly execSync: ExecSync; + private readonly nodeExecSync: ExecSync; private readonly npmPath: string; readonly typesRegistry: Map; @@ -95,7 +99,7 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Process id: ${process.pid}`); this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); } - ({ execSync: this.execSync } = require("child_process")); + ({ execSync: this.nodeExecSync } = require("child_process")); this.ensurePackageDirectoryExists(globalTypingsCacheLocation); @@ -103,7 +107,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Updating ${TypesRegistryPackageName} npm package...`); } - this.execSync(`${this.npmPath} install --ignore-scripts ${TypesRegistryPackageName}`, { cwd: globalTypingsCacheLocation, stdio: "ignore" }); + this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${TypesRegistryPackageName}`, { cwd: globalTypingsCacheLocation }); if (this.log.isEnabled()) { this.log.writeLine(`Updated ${TypesRegistryPackageName} npm package`); } @@ -155,22 +159,31 @@ namespace ts.server.typingsInstaller { } const command = `${this.npmPath} install --ignore-scripts ${args.join(" ")} --save-dev --user-agent="typesInstaller/${version}"`; const start = Date.now(); - let stdout: Buffer; - let stderr: Buffer; - let hasError = false; - try { - stdout = this.execSync(command, { cwd }); - } - catch (e) { - stdout = e.stdout; - stderr = e.stderr; - hasError = true; - } + const hasError = this.execSyncAndLog(command, { cwd }); if (this.log.isEnabled()) { - this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms${sys.newLine}stdout: ${stdout && stdout.toString()}${sys.newLine}stderr: ${stderr && stderr.toString()}`); + this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms`); } onRequestCompleted(!hasError); } + + /** Returns 'true' in case of error. */ + private execSyncAndLog(command: string, options: Pick): boolean { + if (this.log.isEnabled()) { + this.log.writeLine(`Exec: ${command}`); + } + try { + const stdout = this.nodeExecSync(command, { ...options, encoding: "utf-8" }); + if (this.log.isEnabled()) { + this.log.writeLine(` Succeeded. stdout:${indent(sys.newLine, stdout)}`); + } + return false; + } + catch (error) { + const { stdout, stderr } = error; + this.log.writeLine(` Failed. stdout:${indent(sys.newLine, stdout)}${sys.newLine} stderr:${indent(sys.newLine, stderr)}`); + return true; + } + } } const logFilePath = findArgument(server.Arguments.LogFile); @@ -193,4 +206,8 @@ namespace ts.server.typingsInstaller { }); const installer = new NodeTypingsInstaller(globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, /*throttleLimit*/5, log); installer.listen(); + + function indent(newline: string, string: string): string { + return `${newline} ` + string.replace(/\r?\n/, `${newline} `); + } } From 9f4130b204024f33cdc6c8ecafebb70edd7fb4ac Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Oct 2017 14:52:23 -0700 Subject: [PATCH 132/246] Fix incorrect cast target (#19093) Found while updating #18285 to latest master. Not sure what this fixes, but it was definitely incorrect - `node` must be a `Block` at this point, so this cast must have been intended for `node.parent`, which was checked against `TryStatement` right before it. --- src/services/refactors/extractSymbol.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 124a1f720bd79..ba5a6d9d1b5d0 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -375,7 +375,7 @@ namespace ts.refactor.extractSymbol { permittedJumps = PermittedJumps.None; break; case SyntaxKind.Block: - if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (node).finallyBlock === node) { + if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (node.parent).finallyBlock === node) { // allow unconditional returns from finally blocks permittedJumps = PermittedJumps.Return; } From b94924533690661c9b5e6b2ef60b136e624adb83 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 11 Oct 2017 15:13:33 -0700 Subject: [PATCH 133/246] Add ValueModule as a valid object literal type, as they are immutable (#19090) * Add ValueModule as a valid object literal type, as they are immutable * Rename method based on usage --- src/compiler/checker.ts | 10 +++---- .../inferredIndexerOnNamespaceImport.js | 28 +++++++++++++++++++ .../inferredIndexerOnNamespaceImport.symbols | 23 +++++++++++++++ .../inferredIndexerOnNamespaceImport.types | 26 +++++++++++++++++ .../inferredIndexerOnNamespaceImport.ts | 12 ++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/inferredIndexerOnNamespaceImport.js create mode 100644 tests/baselines/reference/inferredIndexerOnNamespaceImport.symbols create mode 100644 tests/baselines/reference/inferredIndexerOnNamespaceImport.types create mode 100644 tests/cases/compiler/inferredIndexerOnNamespaceImport.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36ee2a00eb9cf..a756faae036f1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6274,7 +6274,7 @@ namespace ts { } function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type { - if (isObjectLiteralType(type)) { + if (isObjectTypeWithInferableIndex(type)) { const propTypes: Type[] = []; for (const prop of getPropertiesOfType(type)) { if (kind === IndexKind.String || isNumericLiteralName(prop.escapedName)) { @@ -9831,7 +9831,7 @@ namespace ts { // if T is related to U. return kind === IndexKind.String && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors); } - if (isObjectLiteralType(source)) { + if (isObjectTypeWithInferableIndex(source)) { let related = Ternary.True; if (kind === IndexKind.String) { const sourceNumberInfo = getIndexInfoOfType(source, IndexKind.Number); @@ -10344,11 +10344,11 @@ namespace ts { } /** - * Return true if type was inferred from an object literal or written as an object type literal + * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module * with no call or construct signatures. */ - function isObjectLiteralType(type: Type) { - return type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral)) !== 0 && + function isObjectTypeWithInferableIndex(type: Type) { + return type.symbol && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.ValueModule)) !== 0 && getSignaturesOfType(type, SignatureKind.Call).length === 0 && getSignaturesOfType(type, SignatureKind.Construct).length === 0; } diff --git a/tests/baselines/reference/inferredIndexerOnNamespaceImport.js b/tests/baselines/reference/inferredIndexerOnNamespaceImport.js new file mode 100644 index 0000000000000..10fbc0890b7dc --- /dev/null +++ b/tests/baselines/reference/inferredIndexerOnNamespaceImport.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/inferredIndexerOnNamespaceImport.ts] //// + +//// [foo.ts] +export const x = 3; +export const y = 5; + +//// [bar.ts] +import * as foo from "./foo"; + +function f(map: { [k: string]: number }) { + // ... +} + +f(foo); + +//// [foo.js] +"use strict"; +exports.__esModule = true; +exports.x = 3; +exports.y = 5; +//// [bar.js] +"use strict"; +exports.__esModule = true; +var foo = require("./foo"); +function f(map) { + // ... +} +f(foo); diff --git a/tests/baselines/reference/inferredIndexerOnNamespaceImport.symbols b/tests/baselines/reference/inferredIndexerOnNamespaceImport.symbols new file mode 100644 index 0000000000000..ea0337ee9c27c --- /dev/null +++ b/tests/baselines/reference/inferredIndexerOnNamespaceImport.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/foo.ts === +export const x = 3; +>x : Symbol(x, Decl(foo.ts, 0, 12)) + +export const y = 5; +>y : Symbol(y, Decl(foo.ts, 1, 12)) + +=== tests/cases/compiler/bar.ts === +import * as foo from "./foo"; +>foo : Symbol(foo, Decl(bar.ts, 0, 6)) + +function f(map: { [k: string]: number }) { +>f : Symbol(f, Decl(bar.ts, 0, 29)) +>map : Symbol(map, Decl(bar.ts, 2, 11)) +>k : Symbol(k, Decl(bar.ts, 2, 19)) + + // ... +} + +f(foo); +>f : Symbol(f, Decl(bar.ts, 0, 29)) +>foo : Symbol(foo, Decl(bar.ts, 0, 6)) + diff --git a/tests/baselines/reference/inferredIndexerOnNamespaceImport.types b/tests/baselines/reference/inferredIndexerOnNamespaceImport.types new file mode 100644 index 0000000000000..4a88b2330a0a3 --- /dev/null +++ b/tests/baselines/reference/inferredIndexerOnNamespaceImport.types @@ -0,0 +1,26 @@ +=== tests/cases/compiler/foo.ts === +export const x = 3; +>x : 3 +>3 : 3 + +export const y = 5; +>y : 5 +>5 : 5 + +=== tests/cases/compiler/bar.ts === +import * as foo from "./foo"; +>foo : typeof foo + +function f(map: { [k: string]: number }) { +>f : (map: { [k: string]: number; }) => void +>map : { [k: string]: number; } +>k : string + + // ... +} + +f(foo); +>f(foo) : void +>f : (map: { [k: string]: number; }) => void +>foo : typeof foo + diff --git a/tests/cases/compiler/inferredIndexerOnNamespaceImport.ts b/tests/cases/compiler/inferredIndexerOnNamespaceImport.ts new file mode 100644 index 0000000000000..dd231361d276e --- /dev/null +++ b/tests/cases/compiler/inferredIndexerOnNamespaceImport.ts @@ -0,0 +1,12 @@ +// @filename: foo.ts +export const x = 3; +export const y = 5; + +// @filename: bar.ts +import * as foo from "./foo"; + +function f(map: { [k: string]: number }) { + // ... +} + +f(foo); \ No newline at end of file From 4d7c112ef7f5cd18f5563fff8158cc9e6eef6a98 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Oct 2017 14:21:09 -0700 Subject: [PATCH 134/246] Make sure project root paths of inferred projects are canonical when comparing --- .../unittests/tsserverProjectSystem.ts | 111 +++++++++++++++++- src/server/editorServices.ts | 15 +-- src/server/project.ts | 6 +- .../reference/api/tsserverlibrary.d.ts | 3 +- 4 files changed, 124 insertions(+), 11 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index f7d082128cdf1..b52a6968774ab 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -220,11 +220,11 @@ namespace ts.projectSystem { checkNumberOfProjects(this, count); } } - export function createProjectService(host: server.ServerHost, parameters: CreateProjectServiceParameters = {}) { + export function createProjectService(host: server.ServerHost, parameters: CreateProjectServiceParameters = {}, options?: Partial) { const cancellationToken = parameters.cancellationToken || server.nullCancellationToken; const logger = parameters.logger || nullLogger; const useSingleInferredProject = parameters.useSingleInferredProject !== undefined ? parameters.useSingleInferredProject : false; - return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller, parameters.eventHandler); + return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, parameters.typingsInstaller, parameters.eventHandler, options); } export function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) { @@ -3703,6 +3703,113 @@ namespace ts.projectSystem { assert.equal(projectService.inferredProjects[1].getCompilationSettings().target, ScriptTarget.ESNext); assert.equal(projectService.inferredProjects[2].getCompilationSettings().target, ScriptTarget.ES2015); }); + + function checkInferredProject(inferredProject: server.InferredProject, actualFiles: FileOrFolder[], target: ScriptTarget) { + checkProjectActualFiles(inferredProject, actualFiles.map(f => f.path)); + assert.equal(inferredProject.getCompilationSettings().target, target); + } + + function verifyProjectRootWithCaseSensitivity(useCaseSensitiveFileNames: boolean) { + const files: [FileOrFolder, FileOrFolder, FileOrFolder, FileOrFolder] = [ + { path: "/a/file1.ts", content: "let x = 1;" }, + { path: "/A/file2.ts", content: "let y = 2;" }, + { path: "/b/file2.ts", content: "let x = 3;" }, + { path: "/c/file3.ts", content: "let z = 4;" } + ]; + const host = createServerHost(files, { useCaseSensitiveFileNames }); + const projectService = createProjectService(host, { useSingleInferredProject: true, }, { useInferredProjectPerProjectRoot: true }); + projectService.setCompilerOptionsForInferredProjects({ + allowJs: true, + target: ScriptTarget.ESNext + }); + projectService.setCompilerOptionsForInferredProjects({ + allowJs: true, + target: ScriptTarget.ES2015 + }, "/a"); + + openClientFiles(["/a", "/a", "/b", undefined]); + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2015], + [[files[2]], ScriptTarget.ESNext] + ]); + closeClientFiles(); + + openClientFiles(["/a", "/A", "/b", undefined]); + if (useCaseSensitiveFileNames) { + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0]], ScriptTarget.ES2015], + [[files[1]], ScriptTarget.ESNext], + [[files[2]], ScriptTarget.ESNext] + ]); + } + else { + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2015], + [[files[2]], ScriptTarget.ESNext] + ]); + } + closeClientFiles(); + + projectService.setCompilerOptionsForInferredProjects({ + allowJs: true, + target: ScriptTarget.ES2017 + }, "/A"); + + openClientFiles(["/a", "/a", "/b", undefined]); + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], useCaseSensitiveFileNames ? ScriptTarget.ES2015 : ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] + ]); + closeClientFiles(); + + openClientFiles(["/a", "/A", "/b", undefined]); + if (useCaseSensitiveFileNames) { + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0]], ScriptTarget.ES2015], + [[files[1]], ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] + ]); + } + else { + verifyInferredProjectsState([ + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] + ]); + } + closeClientFiles(); + + function openClientFiles(projectRoots: [string | undefined, string | undefined, string | undefined, string | undefined]) { + files.forEach((file, index) => { + projectService.openClientFile(file.path, file.content, ScriptKind.JS, projectRoots[index]); + }); + } + + function closeClientFiles() { + files.forEach(file => projectService.closeClientFile(file.path)); + } + + function verifyInferredProjectsState(expected: [FileOrFolder[], ScriptTarget][]) { + checkNumberOfProjects(projectService, { inferredProjects: expected.length }); + projectService.inferredProjects.forEach((p, index) => { + const [actualFiles, target] = expected[index]; + checkInferredProject(p, actualFiles, target); + }); + } + } + + it("inferred projects per project root with case sensitive system", () => { + verifyProjectRootWithCaseSensitivity(/*useCaseSensitiveFileNames*/ true); + }); + + it("inferred projects per project root with case insensitive system", () => { + verifyProjectRootWithCaseSensitivity(/*useCaseSensitiveFileNames*/ false); + }); }); describe("No overwrite emit error", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 379a5fbfe7e59..98112b3f24e49 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -590,9 +590,9 @@ namespace ts.server { // always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside // previously we did not expose a way for user to change these settings and this option was enabled by default compilerOptions.allowNonTsExtensions = true; - - if (projectRootPath) { - this.compilerOptionsForInferredProjectsPerProjectRoot.set(projectRootPath, compilerOptions); + const canonicalProjectRootPath = projectRootPath && this.toCanonicalFileName(projectRootPath); + if (canonicalProjectRootPath) { + this.compilerOptionsForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, compilerOptions); } else { this.compilerOptionsForInferredProjects = compilerOptions; @@ -608,9 +608,9 @@ namespace ts.server { // root path // - Inferred projects with a projectRootPath, if the new options apply to that // project root path. - if (projectRootPath ? - project.projectRootPath === projectRootPath : - !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) { + if (canonicalProjectRootPath ? + project.projectRootPath === canonicalProjectRootPath : + !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) { project.setCompilerOptions(compilerOptions); project.compileOnSaveEnabled = compilerOptions.compileOnSave; project.markAsDirty(); @@ -1596,9 +1596,10 @@ namespace ts.server { } if (projectRootPath) { + const canonicalProjectRootPath = this.toCanonicalFileName(projectRootPath); // if we have an explicit project root path, find (or create) the matching inferred project. for (const project of this.inferredProjects) { - if (project.projectRootPath === projectRootPath) { + if (project.projectRootPath === canonicalProjectRootPath) { return project; } } diff --git a/src/server/project.ts b/src/server/project.ts index 9c66f8b4a6c49..bf060b66a273f 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1047,12 +1047,15 @@ namespace ts.server { super.setCompilerOptions(newOptions); } + /** this is canonical project root path */ + readonly projectRootPath: string | undefined; + /*@internal*/ constructor( projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, - readonly projectRootPath: string | undefined, + projectRootPath: string | undefined, currentDirectory: string | undefined) { super(InferredProject.newName(), ProjectKind.Inferred, @@ -1064,6 +1067,7 @@ namespace ts.server { /*compileOnSaveEnabled*/ false, projectService.host, currentDirectory); + this.projectRootPath = projectRootPath && projectService.toCanonicalFileName(projectRootPath); } addRoot(info: ScriptInfo) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index d862513c29387..61320be7eb7b8 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7186,11 +7186,12 @@ declare namespace ts.server { * the file and its imports/references are put into an InferredProject. */ class InferredProject extends Project { - readonly projectRootPath: string | undefined; private static readonly newName; private _isJsInferredProject; toggleJsInferredProject(isJsInferredProject: boolean): void; setCompilerOptions(options?: CompilerOptions): void; + /** this is canonical project root path*/ + readonly projectRootPath: string | undefined; addRoot(info: ScriptInfo): void; removeRoot(info: ScriptInfo): void; isProjectWithSingleRoot(): boolean; From eb4f067ecbdd3b43b9df8ea9c4826b766f38f8b7 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 11 Oct 2017 13:53:52 -0700 Subject: [PATCH 135/246] Don't clobber the position of cloned nodes --- src/services/utilities.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5affb8a888736..a8dea4ddd0e03 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1349,15 +1349,16 @@ namespace ts { const visited = visitEachChild(node, getSynthesizedDeepClone, nullTransformationContext); if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. - return getSynthesizedClone(node); + const clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + return clone; } // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update // the new node created by visitEachChild with the extra changes getSynthesizedClone // would have made. - visited.pos = -1; - visited.end = -1; visited.parent = undefined; return visited; From d00ab417c6a4e5e084c3bbeab9b31ccd9fbc5854 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 11 Oct 2017 15:58:54 -0700 Subject: [PATCH 136/246] checkTypeParameters now always calls fillMissingTypeArguments And refactor checkTypeParameters to be easier to use and to read. --- src/compiler/checker.ts | 61 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 56835e13dde4e..ff78ccaa1355d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15643,34 +15643,35 @@ namespace ts { return getInferredTypes(context); } - function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray, typeArgumentTypes: Type[], reportErrors: boolean, headMessage?: DiagnosticMessage): boolean { + function checkTypeArguments(signature: Signature, typeArguments: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | false { + const isJavascript = isInJavaScriptFile(signature.declaration); const typeParameters = signature.typeParameters; - let typeArgumentsAreAssignable = true; + const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); let mapper: TypeMapper; - for (let i = 0; i < typeArgumentNodes.length; i++) { - if (typeArgumentsAreAssignable /* so far */) { - const constraint = getConstraintOfTypeParameter(typeParameters[i]); - if (constraint) { - let errorInfo: DiagnosticMessageChain; - let typeArgumentHeadMessage = Diagnostics.Type_0_does_not_satisfy_the_constraint_1; - if (reportErrors && headMessage) { - errorInfo = chainDiagnosticMessages(errorInfo, typeArgumentHeadMessage); - typeArgumentHeadMessage = headMessage; - } - if (!mapper) { - mapper = createTypeMapper(typeParameters, typeArgumentTypes); - } - const typeArgument = typeArgumentTypes[i]; - typeArgumentsAreAssignable = checkTypeAssignableTo( - typeArgument, - getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), - reportErrors ? typeArgumentNodes[i] : undefined, - typeArgumentHeadMessage, - errorInfo); + for (let i = 0; i < typeArguments.length; i++) { + const constraint = getConstraintOfTypeParameter(typeParameters[i]); + if (constraint) { + let errorInfo: DiagnosticMessageChain; + let typeArgumentHeadMessage = Diagnostics.Type_0_does_not_satisfy_the_constraint_1; + if (reportErrors && headMessage) { + errorInfo = chainDiagnosticMessages(errorInfo, typeArgumentHeadMessage); + typeArgumentHeadMessage = headMessage; + } + if (!mapper) { + mapper = createTypeMapper(typeParameters, typeArgumentTypes); + } + const typeArgument = typeArgumentTypes[i]; + if (!checkTypeAssignableTo( + typeArgument, + getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), + reportErrors ? typeArguments[i] : undefined, + typeArgumentHeadMessage, + errorInfo)) { + return false; } } } - return typeArgumentsAreAssignable; + return typeArgumentTypes; } /** @@ -16203,10 +16204,7 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - const isJavascript = isInJavaScriptFile(candidateForTypeArgumentError.declaration); - const typeArguments = (node).typeArguments; - const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidateForTypeArgumentError.typeParameters, getMinTypeArgumentCount(candidateForTypeArgumentError.typeParameters), isJavascript); - checkTypeArguments(candidateForTypeArgumentError, typeArguments, typeArgumentTypes, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { let min = Number.POSITIVE_INFINITY; @@ -16305,10 +16303,12 @@ namespace ts { candidate = originalCandidate; if (candidate.typeParameters) { let typeArgumentTypes: Type[]; - const isJavascript = isInJavaScriptFile(candidate.declaration); if (typeArguments) { - typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), candidate.typeParameters, getMinTypeArgumentCount(candidate.typeParameters), isJavascript); - if (!checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)) { + const typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false); + if (typeArgumentResult) { + typeArgumentTypes = typeArgumentResult; + } + else { candidateForTypeArgumentError = originalCandidate; break; } @@ -16316,6 +16316,7 @@ namespace ts { else { typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); } + const isJavascript = isInJavaScriptFile(candidate.declaration); candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript); } if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { From 9ef417b846694bb609e6d2a36b90b87b4e58cc34 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 16:02:58 -0700 Subject: [PATCH 137/246] Account for type queries in type literals --- src/compiler/checker.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed131c8936c44..9224b6afd7c78 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8290,20 +8290,25 @@ namespace ts { function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) { // If the type parameter doesn't have exactly one declaration, if there are invening statement blocks - // between the node and the type parameter declaration, or if the node contains actual references to the - // type parameter, we consider the type parameter possibly referenced. + // between the node and the type parameter declaration, if the node contains actual references to the + // type parameter, or if the node contains type queries, we consider the type parameter possibly referenced. if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { const container = tp.symbol.declarations[0].parent; if (findAncestor(node, n => n.kind === SyntaxKind.Block ? "quit" : n === container)) { - return tp.isThisType ? forEachChild(node, checkThis) : forEachChild(node, checkIdentifier); + return forEachChild(node, containsReference); } } return true; - function checkThis(node: Node): boolean { - return node.kind === SyntaxKind.ThisType || forEachChild(node, checkThis); - } - function checkIdentifier(node: Node): boolean { - return node.kind === SyntaxKind.Identifier && isPartOfTypeNode(node) && getTypeFromTypeNode(node) === tp || forEachChild(node, checkIdentifier); + function containsReference(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.ThisType: + return tp.isThisType; + case SyntaxKind.Identifier: + return !tp.isThisType && isPartOfTypeNode(node) && getTypeFromTypeNode(node) === tp; + case SyntaxKind.TypeQuery: + return true; + } + return forEachChild(node, containsReference); } } From 19f70f6d3dac5ec210e1184631f2bee055e0fb4b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 16:03:15 -0700 Subject: [PATCH 138/246] Add additional test --- tests/cases/compiler/indirectTypeParameterReferences.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/cases/compiler/indirectTypeParameterReferences.ts b/tests/cases/compiler/indirectTypeParameterReferences.ts index 210a599354dc3..c8cb56ad5e714 100644 --- a/tests/cases/compiler/indirectTypeParameterReferences.ts +++ b/tests/cases/compiler/indirectTypeParameterReferences.ts @@ -22,3 +22,8 @@ combined(comb => { comb.b comb.a }) + +// Repro from #19091 + +declare function f(a: T): { a: typeof a }; +let n: number = f(2).a; From 7ee96293ca23b3e8b6b2d64762b9366b2df59b71 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 11 Oct 2017 16:03:23 -0700 Subject: [PATCH 139/246] Accept new baselines --- .../indirectTypeParameterReferences.js | 6 ++++++ .../indirectTypeParameterReferences.symbols | 16 ++++++++++++++++ .../indirectTypeParameterReferences.types | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/tests/baselines/reference/indirectTypeParameterReferences.js b/tests/baselines/reference/indirectTypeParameterReferences.js index e6e807a472038..f947b8f7c1ffb 100644 --- a/tests/baselines/reference/indirectTypeParameterReferences.js +++ b/tests/baselines/reference/indirectTypeParameterReferences.js @@ -23,6 +23,11 @@ combined(comb => { comb.b comb.a }) + +// Repro from #19091 + +declare function f(a: T): { a: typeof a }; +let n: number = f(2).a; //// [indirectTypeParameterReferences.js] @@ -41,3 +46,4 @@ combined(function (comb) { comb.b; comb.a; }); +var n = f(2).a; diff --git a/tests/baselines/reference/indirectTypeParameterReferences.symbols b/tests/baselines/reference/indirectTypeParameterReferences.symbols index 0cb091a86224a..cf0f3e7bbc910 100644 --- a/tests/baselines/reference/indirectTypeParameterReferences.symbols +++ b/tests/baselines/reference/indirectTypeParameterReferences.symbols @@ -73,3 +73,19 @@ combined(comb => { }) +// Repro from #19091 + +declare function f(a: T): { a: typeof a }; +>f : Symbol(f, Decl(indirectTypeParameterReferences.ts, 23, 2)) +>T : Symbol(T, Decl(indirectTypeParameterReferences.ts, 27, 19)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 27, 22)) +>T : Symbol(T, Decl(indirectTypeParameterReferences.ts, 27, 19)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 27, 30)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 27, 22)) + +let n: number = f(2).a; +>n : Symbol(n, Decl(indirectTypeParameterReferences.ts, 28, 3)) +>f(2).a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 27, 30)) +>f : Symbol(f, Decl(indirectTypeParameterReferences.ts, 23, 2)) +>a : Symbol(a, Decl(indirectTypeParameterReferences.ts, 27, 30)) + diff --git a/tests/baselines/reference/indirectTypeParameterReferences.types b/tests/baselines/reference/indirectTypeParameterReferences.types index 2a8ac9a8b0891..e38f5dd2577aa 100644 --- a/tests/baselines/reference/indirectTypeParameterReferences.types +++ b/tests/baselines/reference/indirectTypeParameterReferences.types @@ -86,3 +86,21 @@ combined(comb => { }) +// Repro from #19091 + +declare function f(a: T): { a: typeof a }; +>f : (a: T) => { a: T; } +>T : T +>a : T +>T : T +>a : T +>a : T + +let n: number = f(2).a; +>n : number +>f(2).a : number +>f(2) : { a: number; } +>f : (a: T) => { a: T; } +>2 : 2 +>a : number + From 568c8a3298fa10f1192a5fd3721414d27b0221b5 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 4 Oct 2017 14:09:32 -0700 Subject: [PATCH 140/246] Allow extraction of variable decls used outside the extracted range If there are only declarations, use the new function as the initializer for a destructuring declaration. If there are declarations and writes, changes all of the `const` declarations to `let` and add `| undefined` onto any explicit types. Use destructuring assignment to accomplish both "initialization" and writes. I don't believe there is a case where there are both declarations and a return (since the declarations wouldn't be available after the return). UNDONE: this could probably be generalized to handle binding patterns but, for now, only identifiers are supported. Fixes #18242 Fixes #18855 --- src/harness/unittests/extractFunctions.ts | 136 ++++++++++ src/services/refactors/extractSymbol.ts | 251 ++++++++++++++---- .../extractFunction/extractFunction11.ts | 6 +- .../extractFunction/extractFunction12.ts | 2 +- .../extractFunction/extractFunction6.ts | 6 +- .../extractFunction/extractFunction7.ts | 6 +- ...nction_VariableDeclaration_Const_NoType.js | 14 + ...nction_VariableDeclaration_Const_NoType.ts | 14 + ...Function_VariableDeclaration_Const_Type.ts | 14 + ...ction_VariableDeclaration_ConsumedTwice.ts | 14 + ...ction_VariableDeclaration_DeclaredTwice.js | 16 ++ ...ction_VariableDeclaration_DeclaredTwice.ts | 16 ++ ...Function_VariableDeclaration_Let_NoType.js | 14 + ...Function_VariableDeclaration_Let_NoType.ts | 14 + ...ctFunction_VariableDeclaration_Let_Type.ts | 14 + ...tFunction_VariableDeclaration_Multiple1.ts | 14 + ...tFunction_VariableDeclaration_Multiple2.js | 16 ++ ...tFunction_VariableDeclaration_Multiple2.ts | 16 ++ ...tFunction_VariableDeclaration_Multiple3.ts | 16 ++ ...n_VariableDeclaration_ShorthandProperty.js | 27 ++ ...n_VariableDeclaration_ShorthandProperty.ts | 27 ++ ...extractFunction_VariableDeclaration_Var.js | 14 + ...extractFunction_VariableDeclaration_Var.ts | 14 + ...VariableDeclaration_Writes_Const_NoType.js | 34 +++ ...VariableDeclaration_Writes_Const_NoType.ts | 34 +++ ...n_VariableDeclaration_Writes_Const_Type.ts | 34 +++ ...n_VariableDeclaration_Writes_Let_NoType.js | 34 +++ ...n_VariableDeclaration_Writes_Let_NoType.ts | 34 +++ ...ion_VariableDeclaration_Writes_Let_Type.ts | 34 +++ ...ction_VariableDeclaration_Writes_Mixed1.js | 38 +++ ...ction_VariableDeclaration_Writes_Mixed1.ts | 38 +++ ...ction_VariableDeclaration_Writes_Mixed2.js | 38 +++ ...ction_VariableDeclaration_Writes_Mixed2.ts | 38 +++ ...ction_VariableDeclaration_Writes_Mixed3.ts | 38 +++ ...riableDeclaration_Writes_UnionUndefined.ts | 42 +++ ...Function_VariableDeclaration_Writes_Var.js | 34 +++ ...Function_VariableDeclaration_Writes_Var.ts | 34 +++ tests/cases/fourslash/extract-method14.ts | 2 +- 38 files changed, 1117 insertions(+), 70 deletions(-) create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_Type.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ConsumedTwice.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_Type.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple1.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple3.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts diff --git a/src/harness/unittests/extractFunctions.ts b/src/harness/unittests/extractFunctions.ts index 750e590ca4cec..715a4f5aa0ca0 100644 --- a/src/harness/unittests/extractFunctions.ts +++ b/src/harness/unittests/extractFunctions.ts @@ -360,6 +360,142 @@ function parsePrimaryExpression(): any { export const j = 10; export const y = [#|j * j|]; }`); + + testExtractFunction("extractFunction_VariableDeclaration_Var", ` +[#|var x = 1;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Let_Type", ` +[#|let x: number = 1;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Let_NoType", ` +[#|let x = 1;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Const_Type", ` +[#|const x: number = 1;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Const_NoType", ` +[#|const x = 1;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Multiple1", ` +[#|const x = 1, y: string = "a";|] +x; y; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Multiple2", ` +[#|const x = 1, y = "a"; +const z = 3;|] +x; y; z; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Multiple3", ` +[#|const x = 1, y: string = "a"; +let z = 3;|] +x; y; z; +`); + + testExtractFunction("extractFunction_VariableDeclaration_ConsumedTwice", ` +[#|const x: number = 1;|] +x; x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_DeclaredTwice", ` +[#|var x = 1; +var x = 2;|] +x; +`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Var", ` +function f() { + let a = 1; + [#|var x = 1; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_NoType", ` +function f() { + let a = 1; + [#|let x = 1; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_Type", ` +function f() { + let a = 1; + [#|let x: number = 1; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Const_NoType", ` +function f() { + let a = 1; + [#|const x = 1; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Const_Type", ` +function f() { + let a = 1; + [#|const x: number = 1; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Mixed1", ` +function f() { + let a = 1; + [#|const x = 1; + let y = 2; + a++;|] + a; x; y; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Mixed2", ` +function f() { + let a = 1; + [#|var x = 1; + let y = 2; + a++;|] + a; x; y; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Mixed3", ` +function f() { + let a = 1; + [#|let x: number = 1; + let y = 2; + a++;|] + a; x; y; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_UnionUndefined", ` +function f() { + let a = 1; + [#|let x: number | undefined = 1; + let y: undefined | number = 2; + let z: (undefined | number) = 3; + a++;|] + a; x; y; z; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_ShorthandProperty", ` +function f() { + [#|let x;|] + return { x }; +}`); }); function testExtractFunction(caption: string, text: string) { diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 9defe3dd1f07a..a03bb8436008c 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -137,7 +137,7 @@ namespace ts.refactor.extractSymbol { export const FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); export const CannotExtractIdentifier = createMessage("Select more than a single identifier."); export const CannotExtractExportedEntity = createMessage("Cannot extract exported declaration"); - export const CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns"); + export const CannotWriteInExpression = createMessage("Cannot write back side-effects when extracting an expression"); export const CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor"); export const CannotExtractAmbientBlock = createMessage("Cannot extract code from ambient contexts"); export const CannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes"); @@ -507,15 +507,16 @@ namespace ts.refactor.extractSymbol { } function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { - const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context); + const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); context.cancellationToken.throwIfCancellationRequested(); - return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context); + return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); } function getConstantExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { - const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context); + const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); + Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?"); context.cancellationToken.throwIfCancellationRequested(); const expression = isExpression(target) ? target @@ -674,6 +675,7 @@ namespace ts.refactor.extractSymbol { node: Statement | Expression | Block, scope: Scope, { usages: usagesInScope, typeParameterUsages, substitutions }: ScopeUsages, + exposedVariableDeclarations: ReadonlyArray, range: TargetRange, context: RefactorContext): RefactorEditInfo { @@ -731,10 +733,10 @@ namespace ts.refactor.extractSymbol { // to avoid problems when there are literal types present if (isExpression(node) && !isJS) { const contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType); + returnType = checker.typeToTypeNode(contextualType, scope, NodeBuilderFlags.NoTruncation); } - const { body, returnValueProperty } = transformFunctionBody(node, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); + const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); let newFunction: MethodDeclaration | FunctionDeclaration; if (isClassLike(scope)) { @@ -796,38 +798,114 @@ namespace ts.refactor.extractSymbol { call = createAwait(call); } - if (writes) { + if (exposedVariableDeclarations.length && !writes) { + // No need to mix declarations and writes. + + // How could any variables be exposed if there's a return statement? + Debug.assert(!returnValueProperty); + Debug.assert(!(range.facts & RangeFacts.HasReturn)); + + if (exposedVariableDeclarations.length === 1) { + // Declaring exactly one variable: let x = newFunction(); + const variableDeclaration = exposedVariableDeclarations[0]; + newNodes.push(createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList( + [createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns + variableDeclaration.parent.flags))); + } + else { + // Declaring multiple variables / return properties: + // let {x, y} = newFunction(); + const bindingElements: BindingElement[] = []; + const typeElements: TypeElement[] = []; + let commonNodeFlags = exposedVariableDeclarations[0].parent.flags; + let sawExplicitType = false; + for (const variableDeclaration of exposedVariableDeclarations) { + bindingElements.push(createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, + /*name*/ getSynthesizedDeepClone(variableDeclaration.name))); + + // Being returned through an object literal will have widened the type. + const variableType: TypeNode = checker.typeToTypeNode( + checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), + scope, + NodeBuilderFlags.NoTruncation); + + typeElements.push(createPropertySignature( + /*modifiers*/ undefined, + /*name*/ variableDeclaration.symbol.name, + /*questionToken*/ undefined, + /*type*/ variableType, + /*initializer*/ undefined)); + sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined; + commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; + } + + const typeLiteral: TypeLiteralNode | undefined = sawExplicitType ? createTypeLiteralNode(typeElements) : undefined; + if (typeLiteral) { + setEmitFlags(typeLiteral, EmitFlags.SingleLine); + } + + newNodes.push(createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList( + [createVariableDeclaration( + createObjectBindingPattern(bindingElements), + /*type*/ typeLiteral, + /*initializer*/call)], + commonNodeFlags))); + } + } + else if (exposedVariableDeclarations.length || writes) { + if (exposedVariableDeclarations.length) { + // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping. + for (const variableDeclaration of exposedVariableDeclarations) { + let flags: NodeFlags = variableDeclaration.parent.flags; + if (flags & NodeFlags.Const) { + flags = (flags & ~NodeFlags.Const) | NodeFlags.Let; + } + + newNodes.push(createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList( + [createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + flags))); + } + } + if (returnValueProperty) { // has both writes and return, need to create variable declaration to hold return value; newNodes.push(createVariableStatement( /*modifiers*/ undefined, - [createVariableDeclaration(returnValueProperty, createKeywordTypeNode(SyntaxKind.AnyKeyword))] - )); + createVariableDeclarationList( + [createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], + NodeFlags.Let))); } - const assignments = getPropertyAssignmentsForWrites(writes); + const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { assignments.unshift(createShorthandPropertyAssignment(returnValueProperty)); } // propagate writes back if (assignments.length === 1) { - if (returnValueProperty) { - newNodes.push(createReturn(createIdentifier(returnValueProperty))); - } - else { - newNodes.push(createStatement(createBinary(assignments[0].name, SyntaxKind.EqualsToken, call))); + // We would only have introduced a return value property if there had been + // other assignments to make. + Debug.assert(!returnValueProperty); - if (range.facts & RangeFacts.HasReturn) { - newNodes.push(createReturn()); - } + newNodes.push(createStatement(createAssignment(assignments[0].name, call))); + + if (range.facts & RangeFacts.HasReturn) { + newNodes.push(createReturn()); } } else { // emit e.g. // { a, b, __return } = newFunction(a, b); // return __return; - newNodes.push(createStatement(createBinary(createObjectLiteral(assignments), SyntaxKind.EqualsToken, call))); + newNodes.push(createStatement(createAssignment(createObjectLiteral(assignments), call))); if (returnValueProperty) { newNodes.push(createReturn(createIdentifier(returnValueProperty))); } @@ -861,6 +939,21 @@ namespace ts.refactor.extractSymbol { const renameFilename = renameRange.getSourceFile().fileName; const renameLocation = getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false); return { renameFilename, renameLocation, edits }; + + function getTypeDeepCloneUnionUndefined(typeNode: TypeNode | undefined): TypeNode | undefined { + if (typeNode === undefined) { + return undefined; + } + + const clone = getSynthesizedDeepClone(typeNode); + let withoutParens = clone; + while (isParenthesizedTypeNode(withoutParens)) { + withoutParens = withoutParens.type; + } + return isUnionTypeNode(withoutParens) && find(withoutParens.types, t => t.kind === SyntaxKind.UndefinedKeyword) + ? clone + : createUnionTypeNode([clone, createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); + } } /** @@ -883,7 +976,7 @@ namespace ts.refactor.extractSymbol { const variableType = isJS ? undefined - : checker.typeToTypeNode(checker.getContextualType(node)); + : checker.typeToTypeNode(checker.getContextualType(node), scope, NodeBuilderFlags.NoTruncation); const initializer = transformConstantInitializer(node, substitutions); @@ -1088,21 +1181,22 @@ namespace ts.refactor.extractSymbol { } } - function transformFunctionBody(body: Node, writes: ReadonlyArray, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block, returnValueProperty: string } { - if (isBlock(body) && !writes && substitutions.size === 0) { - // already block, no writes to propagate back, no substitutions - can use node as is + function transformFunctionBody(body: Node, exposedVariableDeclarations: ReadonlyArray, writes: ReadonlyArray, substitutions: ReadonlyMap, hasReturn: boolean): { body: Block, returnValueProperty: string } { + const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; + if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { + // already block, no declarations or writes to propagate back, no substitutions - can use node as is return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } let returnValueProperty: string; let ignoreReturns = false; const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(body)]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions - if (writes || substitutions.size) { + if (hasWritesOrVariableDeclarations || substitutions.size) { const rewrittenStatements = visitNodes(statements, visitor).slice(); - if (writes && !hasReturn && isStatement(body)) { + if (hasWritesOrVariableDeclarations && !hasReturn && isStatement(body)) { // add return at the end to propagate writes back in case if control flow falls out of the function body // it is ok to know that range has at least one return since it we only allow unconditional returns - const assignments = getPropertyAssignmentsForWrites(writes); + const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (assignments.length === 1) { rewrittenStatements.push(createReturn(assignments[0].name)); } @@ -1117,8 +1211,8 @@ namespace ts.refactor.extractSymbol { } function visitor(node: Node): VisitResult { - if (!ignoreReturns && node.kind === SyntaxKind.ReturnStatement && writes) { - const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWrites(writes); + if (!ignoreReturns && node.kind === SyntaxKind.ReturnStatement && hasWritesOrVariableDeclarations) { + const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if ((node).expression) { if (!returnValueProperty) { returnValueProperty = "__return"; @@ -1240,8 +1334,18 @@ namespace ts.refactor.extractSymbol { } } - function getPropertyAssignmentsForWrites(writes: ReadonlyArray): ShorthandPropertyAssignment[] { - return writes.map(w => createShorthandPropertyAssignment(w.symbol.name)); + function getPropertyAssignmentsForWritesAndVariableDeclarations( + exposedVariableDeclarations: ReadonlyArray, + writes: ReadonlyArray) { + + const variableAssignments = map(exposedVariableDeclarations, v => createShorthandPropertyAssignment(v.symbol.name)); + const writeAssignments = map(writes, w => createShorthandPropertyAssignment(w.symbol.name)); + + return variableAssignments === undefined + ? writeAssignments + : writeAssignments === undefined + ? variableAssignments + : variableAssignments.concat(writeAssignments); } function isReadonlyArray(v: any): v is ReadonlyArray { @@ -1287,6 +1391,7 @@ namespace ts.refactor.extractSymbol { readonly usagesPerScope: ReadonlyArray; readonly functionErrorsPerScope: ReadonlyArray>; readonly constantErrorsPerScope: ReadonlyArray>; + readonly exposedVariableDeclarations: ReadonlyArray; } function collectReadsAndWrites( targetRange: TargetRange, @@ -1301,7 +1406,10 @@ namespace ts.refactor.extractSymbol { const substitutionsPerScope: Map[] = []; const functionErrorsPerScope: Diagnostic[][] = []; const constantErrorsPerScope: Diagnostic[][] = []; - const visibleDeclarationsInExtractedRange: Symbol[] = []; + const visibleDeclarationsInExtractedRange: NamedDeclaration[] = []; + const exposedVariableSymbolSet = createMap(); // Key is symbol ID + const exposedVariableDeclarations: VariableDeclaration[] = []; + let firstExposedNonVariableDeclaration: NamedDeclaration | undefined = undefined; const expression = !isReadonlyArray(targetRange.range) ? targetRange.range @@ -1346,7 +1454,6 @@ namespace ts.refactor.extractSymbol { const seenUsages = createMap(); const target = isReadonlyArray(targetRange.range) ? createBlock(targetRange.range) : targetRange.range; - const containingLexicalScopeOfExtraction = isBlockScope(scopes[0], scopes[0].parent) ? scopes[0] : getEnclosingBlockScopeContainer(scopes[0]); const unmodifiedNode = isReadonlyArray(targetRange.range) ? first(targetRange.range) : targetRange.range; const inGenericContext = isInGenericContext(unmodifiedNode); @@ -1392,6 +1499,15 @@ namespace ts.refactor.extractSymbol { Debug.assert(i === scopes.length); } + // If there are any declarations in the extracted block that are used in the same enclosing + // lexical scope, we can't move the extraction "up" as those declarations will become unreachable + if (visibleDeclarationsInExtractedRange.length) { + const containingLexicalScopeOfExtraction = isBlockScope(scopes[0], scopes[0].parent) + ? scopes[0] + : getEnclosingBlockScopeContainer(scopes[0]); + forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations); + } + for (let i = 0; i < scopes.length; i++) { const scopeUsages = usagesPerScope[i]; // Special case: in the innermost scope, all usages are available. @@ -1415,8 +1531,11 @@ namespace ts.refactor.extractSymbol { } }); - if (hasWrite && !isReadonlyArray(targetRange.range) && isExpression(targetRange.range)) { - const diag = createDiagnosticForNode(targetRange.range, Messages.CannotCombineWritesAndReturns); + // If an expression was extracted, then there shouldn't have been any variable declarations. + Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0); + + if (hasWrite && !isReadonlyArray(targetRange.range)) { + const diag = createDiagnosticForNode(targetRange.range, Messages.CannotWriteInExpression); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } @@ -1425,15 +1544,14 @@ namespace ts.refactor.extractSymbol { functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } + else if (firstExposedNonVariableDeclaration) { + const diag = createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.CannotExtractExportedEntity); + functionErrorsPerScope[i].push(diag); + constantErrorsPerScope[i].push(diag); + } } - // If there are any declarations in the extracted block that are used in the same enclosing - // lexical scope, we can't move the extraction "up" as those declarations will become unreachable - if (visibleDeclarationsInExtractedRange.length) { - forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations); - } - - return { target, usagesPerScope, functionErrorsPerScope, constantErrorsPerScope }; + return { target, usagesPerScope, functionErrorsPerScope, constantErrorsPerScope, exposedVariableDeclarations }; function hasTypeParameters(node: Node) { return isDeclarationWithTypeParameters(node) && @@ -1472,7 +1590,7 @@ namespace ts.refactor.extractSymbol { } if (isDeclaration(node) && node.symbol) { - visibleDeclarationsInExtractedRange.push(node.symbol); + visibleDeclarationsInExtractedRange.push(node); } if (isAssignmentExpression(node)) { @@ -1518,11 +1636,7 @@ namespace ts.refactor.extractSymbol { } function recordUsagebySymbol(identifier: Identifier, usage: Usage, isTypeName: boolean) { - // If the identifier is both a property name and its value, we're only interested in its value - // (since the name is a declaration and will be included in the extracted range). - const symbol = identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier - ? checker.getShorthandAssignmentValueSymbol(identifier.parent) - : checker.getSymbolAtLocation(identifier); + const symbol = getSymbolReferencedByIdentifier(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; @@ -1606,20 +1720,39 @@ namespace ts.refactor.extractSymbol { } // Otherwise check and recurse. - const sym = checker.getSymbolAtLocation(node); - if (sym && visibleDeclarationsInExtractedRange.some(d => d === sym)) { - const diag = createDiagnosticForNode(node, Messages.CannotExtractExportedEntity); - for (const errors of functionErrorsPerScope) { - errors.push(diag); - } - for (const errors of constantErrorsPerScope) { - errors.push(diag); + const sym = isIdentifier(node) + ? getSymbolReferencedByIdentifier(node) + : checker.getSymbolAtLocation(node); + if (sym) { + const decl = find(visibleDeclarationsInExtractedRange, d => d.symbol === sym); + if (decl) { + if (isVariableDeclaration(decl)) { + const idString = decl.symbol.id.toString(); + if (!exposedVariableSymbolSet.has(idString)) { + exposedVariableDeclarations.push(decl); + exposedVariableSymbolSet.set(idString, true); + } + } + else { + // CONSIDER: this includes binding elements, which we could + // expose in the same way as variables. + firstExposedNonVariableDeclaration = firstExposedNonVariableDeclaration || decl; + } } - return true; - } - else { - forEachChild(node, checkForUsedDeclarations); } + + forEachChild(node, checkForUsedDeclarations); + } + + /** + * Return the symbol referenced by an identifier (even if it declares a different symbol). + */ + function getSymbolReferencedByIdentifier(identifier: Identifier) { + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). + return identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); } function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName { diff --git a/tests/baselines/reference/extractFunction/extractFunction11.ts b/tests/baselines/reference/extractFunction/extractFunction11.ts index d07a1826439cf..4bb88123a2f40 100644 --- a/tests/baselines/reference/extractFunction/extractFunction11.ts +++ b/tests/baselines/reference/extractFunction/extractFunction11.ts @@ -17,7 +17,7 @@ namespace A { class C { a() { let z = 1; - var __return: any; + let __return; ({ __return, z } = this./*RENAME*/newMethod(z)); return __return; } @@ -36,7 +36,7 @@ namespace A { class C { a() { let z = 1; - var __return: any; + let __return; ({ __return, z } = /*RENAME*/newFunction(z)); return __return; } @@ -55,7 +55,7 @@ namespace A { class C { a() { let z = 1; - var __return: any; + let __return; ({ __return, y, z } = /*RENAME*/newFunction(y, z)); return __return; } diff --git a/tests/baselines/reference/extractFunction/extractFunction12.ts b/tests/baselines/reference/extractFunction/extractFunction12.ts index 37274bdcc87ad..49e87151b9ba7 100644 --- a/tests/baselines/reference/extractFunction/extractFunction12.ts +++ b/tests/baselines/reference/extractFunction/extractFunction12.ts @@ -20,7 +20,7 @@ namespace A { b() {} a() { let z = 1; - var __return: any; + let __return; ({ __return, z } = this./*RENAME*/newMethod(z)); return __return; } diff --git a/tests/baselines/reference/extractFunction/extractFunction6.ts b/tests/baselines/reference/extractFunction/extractFunction6.ts index f6c94216b46aa..a01cb25e06178 100644 --- a/tests/baselines/reference/extractFunction/extractFunction6.ts +++ b/tests/baselines/reference/extractFunction/extractFunction6.ts @@ -43,7 +43,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(a)); return __return; } @@ -65,7 +65,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(a)); return __return; } @@ -87,7 +87,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(x, a)); return __return; } diff --git a/tests/baselines/reference/extractFunction/extractFunction7.ts b/tests/baselines/reference/extractFunction/extractFunction7.ts index 91377868e0f45..4111558904c83 100644 --- a/tests/baselines/reference/extractFunction/extractFunction7.ts +++ b/tests/baselines/reference/extractFunction/extractFunction7.ts @@ -49,7 +49,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(a)); return __return; } @@ -73,7 +73,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(a)); return __return; } @@ -97,7 +97,7 @@ namespace A { function a() { let a = 1; - var __return: any; + let __return; ({ __return, a } = /*RENAME*/newFunction(x, a)); return __return; } diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.js new file mode 100644 index 0000000000000..fff1488ef4141 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +const x = /*RENAME*/newFunction(); +x; + +function newFunction() { + const x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.ts new file mode 100644 index 0000000000000..fff1488ef4141 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_NoType.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +const x = /*RENAME*/newFunction(); +x; + +function newFunction() { + const x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_Type.ts new file mode 100644 index 0000000000000..9457695375870 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Const_Type.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/const x: number = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +const x: number = /*RENAME*/newFunction(); +x; + +function newFunction() { + const x: number = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ConsumedTwice.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ConsumedTwice.ts new file mode 100644 index 0000000000000..ac57711614cd0 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ConsumedTwice.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/const x: number = 1;/*|]*/ +x; x; + +// ==SCOPE::Extract to function in global scope== + +const x: number = /*RENAME*/newFunction(); +x; x; + +function newFunction() { + const x: number = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.js new file mode 100644 index 0000000000000..e6f314acd9c66 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*[#|*/var x = 1; +var x = 2;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +var x = /*RENAME*/newFunction(); +x; + +function newFunction() { + var x = 1; + var x = 2; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.ts new file mode 100644 index 0000000000000..e6f314acd9c66 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_DeclaredTwice.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*[#|*/var x = 1; +var x = 2;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +var x = /*RENAME*/newFunction(); +x; + +function newFunction() { + var x = 1; + var x = 2; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.js new file mode 100644 index 0000000000000..4f407ce570394 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/let x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +let x = /*RENAME*/newFunction(); +x; + +function newFunction() { + let x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.ts new file mode 100644 index 0000000000000..4f407ce570394 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_NoType.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/let x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +let x = /*RENAME*/newFunction(); +x; + +function newFunction() { + let x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_Type.ts new file mode 100644 index 0000000000000..048b77094ea39 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Let_Type.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/let x: number = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +let x: number = /*RENAME*/newFunction(); +x; + +function newFunction() { + let x: number = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple1.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple1.ts new file mode 100644 index 0000000000000..07ec452e36087 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple1.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1, y: string = "a";/*|]*/ +x; y; + +// ==SCOPE::Extract to function in global scope== + +const { x, y }: { x: number; y: string; } = /*RENAME*/newFunction(); +x; y; + +function newFunction() { + const x = 1, y: string = "a"; + return { x, y }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.js new file mode 100644 index 0000000000000..c58c39bf6b884 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1, y = "a"; +const z = 3;/*|]*/ +x; y; z; + +// ==SCOPE::Extract to function in global scope== + +const { x, y, z } = /*RENAME*/newFunction(); +x; y; z; + +function newFunction() { + const x = 1, y = "a"; + const z = 3; + return { x, y, z }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.ts new file mode 100644 index 0000000000000..c58c39bf6b884 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple2.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1, y = "a"; +const z = 3;/*|]*/ +x; y; z; + +// ==SCOPE::Extract to function in global scope== + +const { x, y, z } = /*RENAME*/newFunction(); +x; y; z; + +function newFunction() { + const x = 1, y = "a"; + const z = 3; + return { x, y, z }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple3.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple3.ts new file mode 100644 index 0000000000000..b8ae2b7288326 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Multiple3.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +/*[#|*/const x = 1, y: string = "a"; +let z = 3;/*|]*/ +x; y; z; + +// ==SCOPE::Extract to function in global scope== + +var { x, y, z }: { x: number; y: string; z: number; } = /*RENAME*/newFunction(); +x; y; z; + +function newFunction() { + const x = 1, y: string = "a"; + let z = 3; + return { x, y, z }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js new file mode 100644 index 0000000000000..67b4f64290c45 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js @@ -0,0 +1,27 @@ +// ==ORIGINAL== + +function f() { + /*[#|*/let x;/*|]*/ + return { x }; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let x = /*RENAME*/newFunction(); + return { x }; + + function newFunction() { + let x; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let x = /*RENAME*/newFunction(); + return { x }; +} +function newFunction() { + let x; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts new file mode 100644 index 0000000000000..67b4f64290c45 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts @@ -0,0 +1,27 @@ +// ==ORIGINAL== + +function f() { + /*[#|*/let x;/*|]*/ + return { x }; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let x = /*RENAME*/newFunction(); + return { x }; + + function newFunction() { + let x; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let x = /*RENAME*/newFunction(); + return { x }; +} +function newFunction() { + let x; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.js new file mode 100644 index 0000000000000..5a784c366c1bd --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.js @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/var x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +var x = /*RENAME*/newFunction(); +x; + +function newFunction() { + var x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.ts new file mode 100644 index 0000000000000..5a784c366c1bd --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Var.ts @@ -0,0 +1,14 @@ +// ==ORIGINAL== + +/*[#|*/var x = 1;/*|]*/ +x; + +// ==SCOPE::Extract to function in global scope== + +var x = /*RENAME*/newFunction(); +x; + +function newFunction() { + var x = 1; + return x; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js new file mode 100644 index 0000000000000..1da5a568333e0 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/const x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + const x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + const x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a) { + const x = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts new file mode 100644 index 0000000000000..f93f43ceebf84 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/const x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + const x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + const x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + const x = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts new file mode 100644 index 0000000000000..ec846f7f28840 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/const x: number = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + const x: number = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + const x: number = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: number | undefined; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + const x: number = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js new file mode 100644 index 0000000000000..2f298c8719f6a --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a) { + let x = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts new file mode 100644 index 0000000000000..e4afefa9da633 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + let x = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts new file mode 100644 index 0000000000000..795effbeb7eaa --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: number = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x: number = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x: number = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: number | undefined; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + let x: number = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js new file mode 100644 index 0000000000000..c36557847f79e --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js @@ -0,0 +1,38 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/const x = 1; + let y = 2; + a++;/*|]*/ + a; x; y; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var { x, y } = /*RENAME*/newFunction(); + a; x; y; + + function newFunction() { + const x = 1; + let y = 2; + a++; + return { x, y }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + let y; + ({ x, y, a } = /*RENAME*/newFunction(a)); + a; x; y; +} +function newFunction(a) { + const x = 1; + let y = 2; + a++; + return { x, y, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts new file mode 100644 index 0000000000000..eaeb781bc484a --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts @@ -0,0 +1,38 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/const x = 1; + let y = 2; + a++;/*|]*/ + a; x; y; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var { x, y } = /*RENAME*/newFunction(); + a; x; y; + + function newFunction() { + const x = 1; + let y = 2; + a++; + return { x, y }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x; + let y; + ({ x, y, a } = /*RENAME*/newFunction(a)); + a; x; y; +} +function newFunction(a: number) { + const x = 1; + let y = 2; + a++; + return { x, y, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js new file mode 100644 index 0000000000000..2d1151a549c8d --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js @@ -0,0 +1,38 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/var x = 1; + let y = 2; + a++;/*|]*/ + a; x; y; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var { x, y } = /*RENAME*/newFunction(); + a; x; y; + + function newFunction() { + var x = 1; + let y = 2; + a++; + return { x, y }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + var x; + let y; + ({ x, y, a } = /*RENAME*/newFunction(a)); + a; x; y; +} +function newFunction(a) { + var x = 1; + let y = 2; + a++; + return { x, y, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts new file mode 100644 index 0000000000000..9466b5dc37f82 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts @@ -0,0 +1,38 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/var x = 1; + let y = 2; + a++;/*|]*/ + a; x; y; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var { x, y } = /*RENAME*/newFunction(); + a; x; y; + + function newFunction() { + var x = 1; + let y = 2; + a++; + return { x, y }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + var x; + let y; + ({ x, y, a } = /*RENAME*/newFunction(a)); + a; x; y; +} +function newFunction(a: number) { + var x = 1; + let y = 2; + a++; + return { x, y, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts new file mode 100644 index 0000000000000..604d2a33c43ce --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts @@ -0,0 +1,38 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: number = 1; + let y = 2; + a++;/*|]*/ + a; x; y; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let { x, y }: { x: number; y: number; } = /*RENAME*/newFunction(); + a; x; y; + + function newFunction() { + let x: number = 1; + let y = 2; + a++; + return { x, y }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: number | undefined; + let y; + ({ x, y, a } = /*RENAME*/newFunction(a)); + a; x; y; +} +function newFunction(a: number) { + let x: number = 1; + let y = 2; + a++; + return { x, y, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts new file mode 100644 index 0000000000000..0cf71e45e2836 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts @@ -0,0 +1,42 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: number | undefined = 1; + let y: undefined | number = 2; + let z: (undefined | number) = 3; + a++;/*|]*/ + a; x; y; z; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let { x, y, z }: { x: number; y: number; z: number; } = /*RENAME*/newFunction(); + a; x; y; z; + + function newFunction() { + let x: number | undefined = 1; + let y: undefined | number = 2; + let z: (undefined | number) = 3; + a++; + return { x, y, z }; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: number | undefined; + let y: undefined | number; + let z: (undefined | number); + ({ x, y, z, a } = /*RENAME*/newFunction(a)); + a; x; y; z; +} +function newFunction(a: number) { + let x: number | undefined = 1; + let y: undefined | number = 2; + let z: (undefined | number) = 3; + a++; + return { x, y, z, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js new file mode 100644 index 0000000000000..25e910713d8ab --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/var x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + var x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + var x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a) { + var x = 1; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts new file mode 100644 index 0000000000000..e215e3d097805 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/var x = 1; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + var x = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + var x = 1; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + var x; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + var x = 1; + a++; + return { x, a }; +} diff --git a/tests/cases/fourslash/extract-method14.ts b/tests/cases/fourslash/extract-method14.ts index ea051aabbe75b..ddfd8cbcbd6e1 100644 --- a/tests/cases/fourslash/extract-method14.ts +++ b/tests/cases/fourslash/extract-method14.ts @@ -18,7 +18,7 @@ edit.applyRefactor({ newContent: `function foo() { var i = 10; - var __return: any; + let __return; ({ __return, i } = /*RENAME*/newFunction(i)); return __return; } From c5f40a1b2b77d99d3ed81b4e9ecb3dac41d15e8a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 11 Oct 2017 17:26:41 -0700 Subject: [PATCH 141/246] Add additional deep clone tests --- src/harness/unittests/extractFunctions.ts | 36 +++++++++++++++++++ src/services/utilities.ts | 5 +++ ...ableDeclaration_Writes_Let_LiteralType1.ts | 34 ++++++++++++++++++ ...ableDeclaration_Writes_Let_LiteralType2.ts | 34 ++++++++++++++++++ ...Declaration_Writes_Let_TypeWithComments.ts | 34 ++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts diff --git a/src/harness/unittests/extractFunctions.ts b/src/harness/unittests/extractFunctions.ts index 715a4f5aa0ca0..c69026c0be8af 100644 --- a/src/harness/unittests/extractFunctions.ts +++ b/src/harness/unittests/extractFunctions.ts @@ -438,6 +438,42 @@ function f() { a; x; }`); + // We propagate numericLiteralFlags, but it's not consumed by the emitter, + // so everything comes out decimal. It would be nice to improve this. + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_LiteralType1", ` +function f() { + let a = 1; + [#|let x: 0o10 | 10 | 0b10 = 10; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_LiteralType2", ` +function f() { + let a = 1; + [#|let x: "a" | 'b' = 'a'; + a++;|] + a; x; +}`); + + // We propagate numericLiteralFlags, but it's not consumed by the emitter, + // so everything comes out decimal. It would be nice to improve this. + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_LiteralType1", ` +function f() { + let a = 1; + [#|let x: 0o10 | 10 | 0b10 = 10; + a++;|] + a; x; +}`); + + testExtractFunction("extractFunction_VariableDeclaration_Writes_Let_TypeWithComments", ` +function f() { + let a = 1; + [#|let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = 'a'; + a++;|] + a; x; +}`); + testExtractFunction("extractFunction_VariableDeclaration_Writes_Const_NoType", ` function f() { let a = 1; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a8dea4ddd0e03..c57b82bc8b8fd 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1350,6 +1350,11 @@ namespace ts { if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. const clone = getSynthesizedClone(node); + if (isStringLiteral(clone)) { + clone.textSourceNode = node as any; + } else if (isNumericLiteral(clone)) { + clone.numericLiteralFlags = (node as any).numericLiteralFlags; + } clone.pos = node.pos; clone.end = node.end; return clone; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts new file mode 100644 index 0000000000000..50bad34efceff --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: 0o10 | 10 | 0b10 = 10; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x: 8 | 10 | 2 = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x: 0o10 | 10 | 0b10 = 10; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: (8 | 10 | 2) | undefined; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + let x: 0o10 | 10 | 0b10 = 10; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts new file mode 100644 index 0000000000000..2df8ab67e9fe2 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: "a" | 'b' = 'a'; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x: "a" | 'b' = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x: "a" | 'b' = 'a'; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: ("a" | 'b') | undefined; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + let x: "a" | 'b' = 'a'; + a++; + return { x, a }; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts new file mode 100644 index 0000000000000..53599c26d08b4 --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts @@ -0,0 +1,34 @@ +// ==ORIGINAL== + +function f() { + let a = 1; + /*[#|*/let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = 'a'; + a++;/*|]*/ + a; x; +} +// ==SCOPE::Extract to inner function in function 'f'== + +function f() { + let a = 1; + let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = /*RENAME*/newFunction(); + a; x; + + function newFunction() { + let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = 'a'; + a++; + return x; + } +} +// ==SCOPE::Extract to function in global scope== + +function f() { + let a = 1; + let x: (/*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/) | undefined; + ({ x, a } = /*RENAME*/newFunction(a)); + a; x; +} +function newFunction(a: number) { + let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = 'a'; + a++; + return { x, a }; +} From 1b896c2f80d7283fa06dd6dca17568e627f5af13 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Wed, 11 Oct 2017 17:35:52 -0700 Subject: [PATCH 142/246] Fix lint error --- src/services/utilities.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index c57b82bc8b8fd..0eb3f88cc9a77 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1352,7 +1352,8 @@ namespace ts { const clone = getSynthesizedClone(node); if (isStringLiteral(clone)) { clone.textSourceNode = node as any; - } else if (isNumericLiteral(clone)) { + } + else if (isNumericLiteral(clone)) { clone.numericLiteralFlags = (node as any).numericLiteralFlags; } clone.pos = node.pos; From 625486455d5a4333fa564772c488b014f7967424 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Oct 2017 09:02:22 -0700 Subject: [PATCH 143/246] Update public api baseline --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 61320be7eb7b8..baa7abbbd9c22 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7190,7 +7190,7 @@ declare namespace ts.server { private _isJsInferredProject; toggleJsInferredProject(isJsInferredProject: boolean): void; setCompilerOptions(options?: CompilerOptions): void; - /** this is canonical project root path*/ + /** this is canonical project root path */ readonly projectRootPath: string | undefined; addRoot(info: ScriptInfo): void; removeRoot(info: ScriptInfo): void; From 73826bdb7b921e1bf497f97e95ef9ce5e01e5857 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 3 Oct 2017 15:39:12 -0700 Subject: [PATCH 144/246] Allow Extract Constant into enclosing scope in spite of RangeFacts.UsesThis --- src/harness/unittests/extractConstants.ts | 24 +++++++++++++++++ src/services/refactors/extractSymbol.ts | 5 +++- .../extractConstant_This_Constructor.js | 16 ++++++++++++ .../extractConstant_This_Constructor.ts | 26 +++++++++++++++++++ .../extractConstant_This_Method.js | 16 ++++++++++++ .../extractConstant_This_Method.ts | 26 +++++++++++++++++++ .../extractConstant_This_Property.ts | 18 +++++++++++++ tests/cases/fourslash/extract-method20.ts | 5 ++-- 8 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/extractConstant/extractConstant_This_Constructor.js create mode 100644 tests/baselines/reference/extractConstant/extractConstant_This_Constructor.ts create mode 100644 tests/baselines/reference/extractConstant/extractConstant_This_Method.js create mode 100644 tests/baselines/reference/extractConstant/extractConstant_This_Method.ts create mode 100644 tests/baselines/reference/extractConstant/extractConstant_This_Property.ts diff --git a/src/harness/unittests/extractConstants.ts b/src/harness/unittests/extractConstants.ts index c5ddc18fea4fe..09f8db34f31fe 100644 --- a/src/harness/unittests/extractConstants.ts +++ b/src/harness/unittests/extractConstants.ts @@ -230,6 +230,30 @@ function f(): void { } testExtractConstantFailed("extractConstant_Never", ` function f(): never { } [#|f();|]`); + + testExtractConstant("extractConstant_This_Constructor", ` +class C { + constructor() { + [#|this.m2()|]; + } + m2() { return 1; } +}`); + + testExtractConstant("extractConstant_This_Method", ` +class C { + m1() { + [#|this.m2()|]; + } + m2() { return 1; } +}`); + + testExtractConstant("extractConstant_This_Property", ` +namespace N { // Force this test to be TS-only + class C { + x = 1; + y = [#|this.x|]; + } +}`); }); function testExtractConstant(caption: string, text: string) { diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index a03bb8436008c..9dd148e5420fa 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -476,7 +476,10 @@ namespace ts.refactor.extractSymbol { // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class const containingClass = getContainingClass(current); if (containingClass) { - return [containingClass]; + const containingFunction = findAncestor(current, isFunctionLikeDeclaration); + return containingFunction + ? [containingFunction, containingClass] + : [containingClass]; } } diff --git a/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.js b/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.js new file mode 100644 index 0000000000000..cf45ab2cd3f9b --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +class C { + constructor() { + /*[#|*/this.m2()/*|]*/; + } + m2() { return 1; } +} +// ==SCOPE::Extract to constant in enclosing scope== + +class C { + constructor() { + const /*RENAME*/newLocal = this.m2(); + } + m2() { return 1; } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.ts b/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.ts new file mode 100644 index 0000000000000..d36d1a6fa2181 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_This_Constructor.ts @@ -0,0 +1,26 @@ +// ==ORIGINAL== + +class C { + constructor() { + /*[#|*/this.m2()/*|]*/; + } + m2() { return 1; } +} +// ==SCOPE::Extract to constant in enclosing scope== + +class C { + constructor() { + const /*RENAME*/newLocal = this.m2(); + } + m2() { return 1; } +} +// ==SCOPE::Extract to readonly field in class 'C'== + +class C { + private readonly newProperty = this.m2(); + + constructor() { + this./*RENAME*/newProperty; + } + m2() { return 1; } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_This_Method.js b/tests/baselines/reference/extractConstant/extractConstant_This_Method.js new file mode 100644 index 0000000000000..fd703868e9f0b --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_This_Method.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +class C { + m1() { + /*[#|*/this.m2()/*|]*/; + } + m2() { return 1; } +} +// ==SCOPE::Extract to constant in enclosing scope== + +class C { + m1() { + const /*RENAME*/newLocal = this.m2(); + } + m2() { return 1; } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_This_Method.ts b/tests/baselines/reference/extractConstant/extractConstant_This_Method.ts new file mode 100644 index 0000000000000..0dbaa4372d42a --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_This_Method.ts @@ -0,0 +1,26 @@ +// ==ORIGINAL== + +class C { + m1() { + /*[#|*/this.m2()/*|]*/; + } + m2() { return 1; } +} +// ==SCOPE::Extract to constant in enclosing scope== + +class C { + m1() { + const /*RENAME*/newLocal = this.m2(); + } + m2() { return 1; } +} +// ==SCOPE::Extract to readonly field in class 'C'== + +class C { + private readonly newProperty = this.m2(); + + m1() { + this./*RENAME*/newProperty; + } + m2() { return 1; } +} \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_This_Property.ts b/tests/baselines/reference/extractConstant/extractConstant_This_Property.ts new file mode 100644 index 0000000000000..04b3b50da1bf3 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_This_Property.ts @@ -0,0 +1,18 @@ +// ==ORIGINAL== + +namespace N { // Force this test to be TS-only + class C { + x = 1; + y = /*[#|*/this.x/*|]*/; + } +} +// ==SCOPE::Extract to readonly field in class 'C'== + +namespace N { // Force this test to be TS-only + class C { + x = 1; + private readonly newProperty = this.x; + + y = this./*RENAME*/newProperty; + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/extract-method20.ts b/tests/cases/fourslash/extract-method20.ts index 75927f0fd5c9e..bd137c55d1975 100644 --- a/tests/cases/fourslash/extract-method20.ts +++ b/tests/cases/fourslash/extract-method20.ts @@ -10,5 +10,6 @@ //// } goTo.select('a', 'b') -verify.refactorAvailable('Extract Symbol', 'function_scope_0'); -verify.not.refactorAvailable('Extract Symbol', 'function_scope_1'); +verify.not.refactorAvailable('Extract Symbol', 'function_scope_0'); +verify.refactorAvailable('Extract Symbol', 'function_scope_1'); +verify.not.refactorAvailable('Extract Symbol', 'function_scope_2'); From e4313f62c66375316dd9c6e979e770f3c36c8e27 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 12 Oct 2017 09:44:02 -0700 Subject: [PATCH 145/246] Add missing test coverage for jumps in finally blocks --- src/harness/unittests/extractRanges.ts | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/harness/unittests/extractRanges.ts b/src/harness/unittests/extractRanges.ts index 2ddcac482a903..a467bb23e0f38 100644 --- a/src/harness/unittests/extractRanges.ts +++ b/src/harness/unittests/extractRanges.ts @@ -152,6 +152,16 @@ namespace ts { } } `); + testExtractRange(` + function f(x: number) { + [#|[$|try { + x++; + } + finally { + return 1; + }|]|] + } + `); }); testExtractRangeFailed("extractRangeFailed1", @@ -313,6 +323,23 @@ switch (x) { refactor.extractSymbol.Messages.CannotExtractRange.message ]); + testExtractRangeFailed("extractRangeFailed11", + ` + function f(x: number) { + while (true) { + [#|try { + x++; + } + finally { + break; + }|] + } + } + `, + [ + refactor.extractSymbol.Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements.message + ]); + testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.CannotExtractIdentifier.message]); }); } \ No newline at end of file From da0c79f2a3fe4793c00b1c47274c36e26a0ff2c4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 10:09:52 -0700 Subject: [PATCH 146/246] Simplify checkTypeArguments based on PR comments --- src/compiler/checker.ts | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff78ccaa1355d..a58fa1cc9b55d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15643,32 +15643,28 @@ namespace ts { return getInferredTypes(context); } - function checkTypeArguments(signature: Signature, typeArguments: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | false { + function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | false { const isJavascript = isInJavaScriptFile(signature.declaration); const typeParameters = signature.typeParameters; - const typeArgumentTypes = fillMissingTypeArguments(map(typeArguments, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); + const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); let mapper: TypeMapper; - for (let i = 0; i < typeArguments.length; i++) { + for (let i = 0; i < typeArgumentNodes.length; i++) { const constraint = getConstraintOfTypeParameter(typeParameters[i]); - if (constraint) { - let errorInfo: DiagnosticMessageChain; - let typeArgumentHeadMessage = Diagnostics.Type_0_does_not_satisfy_the_constraint_1; - if (reportErrors && headMessage) { - errorInfo = chainDiagnosticMessages(errorInfo, typeArgumentHeadMessage); - typeArgumentHeadMessage = headMessage; - } - if (!mapper) { - mapper = createTypeMapper(typeParameters, typeArgumentTypes); - } - const typeArgument = typeArgumentTypes[i]; - if (!checkTypeAssignableTo( - typeArgument, - getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), - reportErrors ? typeArguments[i] : undefined, - typeArgumentHeadMessage, - errorInfo)) { - return false; - } + if (!constraint) continue; + + const errorInfo = reportErrors && headMessage && chainDiagnosticMessages(undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1; + if (!mapper) { + mapper = createTypeMapper(typeParameters, typeArgumentTypes); + } + const typeArgument = typeArgumentTypes[i]; + if (!checkTypeAssignableTo( + typeArgument, + getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument), + reportErrors ? typeArgumentNodes[i] : undefined, + typeArgumentHeadMessage, + errorInfo)) { + return false; } } return typeArgumentTypes; From 8ea13bef48cc276634e770009144995b843f5553 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 10:11:09 -0700 Subject: [PATCH 147/246] Fix lint --- 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 a58fa1cc9b55d..3380e89cd0f56 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15652,7 +15652,7 @@ namespace ts { const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (!constraint) continue; - const errorInfo = reportErrors && headMessage && chainDiagnosticMessages(undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + const errorInfo = reportErrors && headMessage && chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); From 4487917f89bd5e068a4d35e8db22bf728cab4b74 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 12 Oct 2017 10:14:58 -0700 Subject: [PATCH 148/246] Quick fix for no-implicit-any errors to add explicit type annotation (#14786) * Infer from usage quick fix * Change full function singature * Add property/element access support * Fix a few issues * Some cleanup * Expose getArrayType and getPromiseType * Switch to collecting all usage before infering * Infer array and promise type arguments * Handel enums in binary operators * consolidate usage of addCandidateTypes * Handel rest paramters * Properly handel `+=` and `+` inference for numbers and strings * Add print quickfixes debug helper * Add rest param tests * Add optional paramter tests * Handel set accessors * Support getters * Support no implicit any error for variable at use site * Support properties * Only offer quick fix if an infered type other than any is available * Rename functions * Move to a separate namespace * Check cancellation token * Cleanup * Check for accesibile symbols where serializing types * Remove JS support * Reorganize functions * Mark APIs as internal * Fix lint errors * Removed conflict markers. * Update 'createSymbol' to use '__String'. * Fixed most problems relating to '__String' and 'includeJsDocComments' in the fix itself. * Addressed most API changes. * Make all helpers internal * Use a diffrent writer and not the built-in single line write * Infer types for all parameters in a parameter list instead of one at a time * Accept baselines * Code review commments * Respond to code review comments --- src/compiler/checker.ts | 18 + src/compiler/core.ts | 6 +- src/compiler/diagnosticMessages.json | 16 +- src/compiler/types.ts | 18 + src/compiler/utilities.ts | 8 + src/services/codefixes/fixes.ts | 1 + src/services/codefixes/inferFromUsage.ts | 653 ++++++++++++++++++ .../reference/api/tsserverlibrary.d.ts | 2 + tests/baselines/reference/api/typescript.d.ts | 2 + .../cases/fourslash/codeFixInferFromUsage.ts | 9 + .../fourslash/codeFixInferFromUsageGetter.ts | 10 + .../fourslash/codeFixInferFromUsageGetter2.ts | 11 + .../codeFixInferFromUsageInaccessibleTypes.ts | 20 + .../fourslash/codeFixInferFromUsageMember.ts | 11 + .../fourslash/codeFixInferFromUsageMember2.ts | 10 + .../fourslash/codeFixInferFromUsageMember3.ts | 9 + ...codeFixInferFromUsageMultipleParameters.ts | 9 + .../codeFixInferFromUsageOptionalParam.ts | 9 + .../codeFixInferFromUsageOptionalParam2.ts | 8 + .../codeFixInferFromUsageRestParam.ts | 11 + .../codeFixInferFromUsageRestParam2.ts | 11 + .../codeFixInferFromUsageRestParam3.ts | 8 + .../fourslash/codeFixInferFromUsageSetter.ts | 10 + .../fourslash/codeFixInferFromUsageSetter2.ts | 10 + .../codeFixInferFromUsageVariable.ts | 9 + .../codeFixInferFromUsageVariable2.ts | 13 + 26 files changed, 893 insertions(+), 9 deletions(-) create mode 100644 src/services/codefixes/inferFromUsage.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsage.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageGetter.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageGetter2.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageInaccessibleTypes.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageMember.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageMember2.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageMember3.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageMultipleParameters.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageOptionalParam.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageOptionalParam2.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageRestParam.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageRestParam2.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageRestParam3.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageSetter.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageSetter2.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageVariable.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsageVariable2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index efdf4589be440..e835fb6c82854 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -226,6 +226,23 @@ namespace ts { return tryFindAmbientModule(moduleName, /*withAugmentations*/ false); }, getApparentType, + getUnionType, + createAnonymousType, + createSignature, + createSymbol, + createIndexInfo, + getAnyType: () => anyType, + getStringType: () => stringType, + getNumberType: () => numberType, + createPromiseType, + createArrayType, + getBooleanType: () => booleanType, + getVoidType: () => voidType, + getUndefinedType: () => undefinedType, + getNullType: () => nullType, + getESSymbolType: () => esSymbolType, + getNeverType: () => neverType, + isSymbolAccessible, isArrayLikeType, getAllPossiblePropertiesOfTypes, getSuggestionForNonexistentProperty: (node, type) => getSuggestionForNonexistentProperty(node, type), @@ -3675,6 +3692,7 @@ namespace ts { function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { const parameterNode = p.valueDeclaration; + if (parameterNode ? isRestParameter(parameterNode) : isTransientSymbol(p) && p.isRestParameter) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index af02cec79c501..f838d6abfef22 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -213,11 +213,13 @@ namespace ts { return undefined; } - export function zipWith(arrayA: ReadonlyArray, arrayB: ReadonlyArray, callback: (a: T, b: U, index: number) => void): void { + export function zipWith(arrayA: ReadonlyArray, arrayB: ReadonlyArray, callback: (a: T, b: U, index: number) => V): V[] { + const result: V[] = []; Debug.assert(arrayA.length === arrayB.length); for (let i = 0; i < arrayA.length; i++) { - callback(arrayA[i], arrayB[i], i); + result.push(callback(arrayA[i], arrayB[i], i)); } + return result; } export function zipToMap(keys: ReadonlyArray, values: ReadonlyArray): Map { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5b601c1b2a1dd..1db368bb54186 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3681,6 +3681,7 @@ "category": "Message", "code": 90017 }, + "Disable checking for this file.": { "category": "Message", "code": 90018 @@ -3725,7 +3726,6 @@ "category": "Message", "code": 90028 }, - "Convert function to an ES2015 class": { "category": "Message", "code": 95001 @@ -3734,34 +3734,36 @@ "category": "Message", "code": 95002 }, - "Extract symbol": { "category": "Message", "code": 95003 }, - "Extract to {0} in {1}": { "category": "Message", "code": 95004 }, - "Extract function": { "category": "Message", "code": 95005 }, - "Extract constant": { "category": "Message", "code": 95006 }, - "Extract to {0} in enclosing scope": { "category": "Message", "code": 95007 }, - "Extract to {0} in {1} scope": { "category": "Message", "code": 95008 + }, + "Infer type of '{0}' from usage.": { + "category": "Message", + "code": 95009 + }, + "Infer parameter types from usage.": { + "category": "Message", + "code": 95010 } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 528664f5eeeff..42e8292b13bd8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2695,6 +2695,24 @@ namespace ts { getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; /* @internal */ getBaseConstraintOfType(type: Type): Type | undefined; + /* @internal */ getAnyType(): Type; + /* @internal */ getStringType(): Type; + /* @internal */ getNumberType(): Type; + /* @internal */ getBooleanType(): Type; + /* @internal */ getVoidType(): Type; + /* @internal */ getUndefinedType(): Type; + /* @internal */ getNullType(): Type; + /* @internal */ getESSymbolType(): Type; + /* @internal */ getNeverType(): Type; + /* @internal */ getUnionType(types: Type[], subtypeReduction?: boolean): Type; + /* @internal */ createArrayType(elementType: Type): Type; + /* @internal */ createPromiseType(type: Type): Type; + + /* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): Type; + /* @internal */ createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[], resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature; + /* @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol; + /* @internal */ createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo; + /* @internal */ isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; /* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; /* @internal */ getSymbolWalker(accept?: (symbol: Symbol) => boolean): SymbolWalker; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 291e1f2fa6669..4688a7779e383 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5649,6 +5649,14 @@ namespace ts { return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode; } + export function isSetAccessor(node: Node): node is SetAccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor; + } + + export function isGetAccessor(node: Node): node is GetAccessorDeclaration { + return node.kind === SyntaxKind.GetAccessor; + } + /** True if has jsdoc nodes attached to it. */ /* @internal */ export function hasJSDocNodes(node: Node): node is HasJSDoc { diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index b024dfae7cd82..7ee0aaa679973 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -13,3 +13,4 @@ /// /// /// +/// diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts new file mode 100644 index 0000000000000..046eb915c1ef6 --- /dev/null +++ b/src/services/codefixes/inferFromUsage.ts @@ -0,0 +1,653 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [ + // Variable declarations + Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code, + + // Variable uses + Diagnostics.Variable_0_implicitly_has_an_1_type.code, + + // Parameter declarations + Diagnostics.Parameter_0_implicitly_has_an_1_type.code, + Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code, + + // Get Accessor declarations + Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code, + Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code, + + // Set Accessor declarations + Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code, + + // Property declarations + Diagnostics.Member_0_implicitly_has_an_1_type.code, + ], + getCodeActions: getActionsForAddExplicitTypeAnnotation + }); + + function getActionsForAddExplicitTypeAnnotation({ sourceFile, program, span: { start }, errorCode, cancellationToken }: CodeFixContext): CodeAction[] | undefined { + const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); + let writer: StringSymbolWriter; + + if (isInJavaScriptFile(token)) { + return undefined; + } + + switch (token.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.DotDotDotToken: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.ReadonlyKeyword: + // Allowed + break; + default: + return undefined; + } + + const containingFunction = getContainingFunction(token); + const checker = program.getTypeChecker(); + + switch (errorCode) { + // Variable and Property declarations + case Diagnostics.Member_0_implicitly_has_an_1_type.code: + case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: + return getCodeActionForVariableDeclaration(token.parent); + case Diagnostics.Variable_0_implicitly_has_an_1_type.code: + return getCodeActionForVariableUsage(token); + + // Parameter declarations + case Diagnostics.Parameter_0_implicitly_has_an_1_type.code: + if (isSetAccessor(containingFunction)) { + return getCodeActionForSetAccessor(containingFunction); + } + // falls through + case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: + return getCodeActionForParameters(token.parent); + + // Get Accessor declarations + case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code: + case Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code: + return isGetAccessor(containingFunction) ? getCodeActionForGetAccessor(containingFunction) : undefined; + + // Set Accessor declarations + case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code: + return isSetAccessor(containingFunction) ? getCodeActionForSetAccessor(containingFunction) : undefined; + } + + return undefined; + + function getCodeActionForVariableDeclaration(declaration: VariableDeclaration | PropertyDeclaration | PropertySignature) { + if (!isIdentifier(declaration.name)) { + return undefined; + } + + const type = inferTypeForVariableFromUsage(declaration.name); + const typeString = type && typeToString(type, declaration); + + if (!typeString) { + return undefined; + } + + return createCodeActions(declaration.name.getText(), declaration.name.getEnd(), `: ${typeString}`); + } + + function getCodeActionForVariableUsage(token: Identifier) { + const symbol = checker.getSymbolAtLocation(token); + return symbol && symbol.valueDeclaration && getCodeActionForVariableDeclaration(symbol.valueDeclaration); + } + + function isApplicableFunctionForInference(declaration: FunctionLike): declaration is MethodDeclaration | FunctionDeclaration | ConstructorDeclaration { + switch (declaration.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + return true; + case SyntaxKind.FunctionExpression: + return !!(declaration as FunctionExpression).name; + } + return false; + } + + function getCodeActionForParameters(parameterDeclaration: ParameterDeclaration): CodeAction[] { + if (!isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) { + return undefined; + } + + const types = inferTypeForParametersFromUsage(containingFunction) || + map(containingFunction.parameters, p => isIdentifier(p.name) && inferTypeForVariableFromUsage(p.name)); + + if (!types) { + return undefined; + } + + const textChanges: TextChange[] = zipWith(containingFunction.parameters, types, (parameter, type) => { + if (type && !parameter.type && !parameter.initializer) { + const typeString = typeToString(type, containingFunction); + return typeString ? { + span: { start: parameter.end, length: 0 }, + newText: `: ${typeString}` + } : undefined; + } + }).filter(c => !!c); + + return textChanges.length ? [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Infer_parameter_types_from_usage), [parameterDeclaration.name.getText()]), + changes: [{ + fileName: sourceFile.fileName, + textChanges + }] + }] : undefined; + } + + function getCodeActionForSetAccessor(setAccessorDeclaration: SetAccessorDeclaration) { + const setAccessorParameter = setAccessorDeclaration.parameters[0]; + if (!setAccessorParameter || !isIdentifier(setAccessorDeclaration.name) || !isIdentifier(setAccessorParameter.name)) { + return undefined; + } + + const type = inferTypeForVariableFromUsage(setAccessorDeclaration.name) || + inferTypeForVariableFromUsage(setAccessorParameter.name); + const typeString = type && typeToString(type, containingFunction); + if (!typeString) { + return undefined; + } + + return createCodeActions(setAccessorDeclaration.name.getText(), setAccessorParameter.name.getEnd(), `: ${typeString}`); + } + + function getCodeActionForGetAccessor(getAccessorDeclaration: GetAccessorDeclaration) { + if (!isIdentifier(getAccessorDeclaration.name)) { + return undefined; + } + + const type = inferTypeForVariableFromUsage(getAccessorDeclaration.name); + const typeString = type && typeToString(type, containingFunction); + if (!typeString) { + return undefined; + } + + const closeParenToken = getFirstChildOfKind(getAccessorDeclaration, sourceFile, SyntaxKind.CloseParenToken); + return createCodeActions(getAccessorDeclaration.name.getText(), closeParenToken.getEnd(), `: ${typeString}`); + } + + function createCodeActions(name: string, start: number, typeString: string) { + return [{ + description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Infer_type_of_0_from_usage), [name]), + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start, length: 0 }, + newText: typeString + }] + }] + }]; + } + + function getReferences(token: PropertyName | Token) { + const references = FindAllReferences.findReferencedSymbols( + program, + cancellationToken, + program.getSourceFiles(), + token.getSourceFile(), + token.getStart()); + + Debug.assert(!!references, "Found no references!"); + Debug.assert(references.length === 1, "Found more references than expected"); + + return map(references[0].references, r => getTokenAtPosition(program.getSourceFile(r.fileName), r.textSpan.start, /*includeJsDocComment*/ false)); + } + + function inferTypeForVariableFromUsage(token: Identifier) { + return InferFromReference.inferTypeFromReferences(getReferences(token), checker, cancellationToken); + } + + function inferTypeForParametersFromUsage(containingFunction: FunctionLikeDeclaration) { + switch (containingFunction.kind) { + case SyntaxKind.Constructor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + const isConstructor = containingFunction.kind === SyntaxKind.Constructor; + const searchToken = isConstructor ? + >getFirstChildOfKind(containingFunction, sourceFile, SyntaxKind.ConstructorKeyword) : + containingFunction.name; + if (searchToken) { + return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken), containingFunction, checker, cancellationToken); + } + } + } + + function getTypeAccessiblityWriter() { + if (!writer) { + let str = ""; + let typeIsAccessible = true; + + const writeText: (text: string) => void = text => str += text; + writer = { + string: () => typeIsAccessible ? str : undefined, + writeKeyword: writeText, + writeOperator: writeText, + writePunctuation: writeText, + writeSpace: writeText, + writeStringLiteral: writeText, + writeParameter: writeText, + writeProperty: writeText, + writeSymbol: writeText, + writeLine: () => str += " ", + increaseIndent: noop, + decreaseIndent: noop, + clear: () => { str = ""; typeIsAccessible = true; }, + trackSymbol: (symbol, declaration, meaning) => { + if (checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility !== SymbolAccessibility.Accessible) { + typeIsAccessible = false; + } + }, + reportInaccessibleThisError: () => { typeIsAccessible = false; }, + reportPrivateInBaseOfClassExpression: () => { typeIsAccessible = false; }, + }; + } + writer.clear(); + return writer; + } + + function typeToString(type: Type, enclosingDeclaration: Declaration) { + const writer = getTypeAccessiblityWriter(); + checker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration); + return writer.string(); + } + + function getFirstChildOfKind(node: Node, sourcefile: SourceFile, kind: SyntaxKind) { + for (const child of node.getChildren(sourcefile)) { + if (child.kind === kind) return child; + } + return undefined; + } + } + + namespace InferFromReference { + interface CallContext { + argumentTypes: Type[]; + returnType: UsageContext; + } + + interface UsageContext { + isNumber?: boolean; + isString?: boolean; + isNumberOrString?: boolean; + candidateTypes?: Type[]; + properties?: UnderscoreEscapedMap; + callContexts?: CallContext[]; + constructContexts?: CallContext[]; + numberIndexContext?: UsageContext; + stringIndexContext?: UsageContext; + } + + export function inferTypeFromReferences(references: Identifier[], checker: TypeChecker, cancellationToken: CancellationToken): Type | undefined { + const usageContext: UsageContext = {}; + for (const reference of references) { + cancellationToken.throwIfCancellationRequested(); + inferTypeFromContext(reference, checker, usageContext); + } + return getTypeFromUsageContext(usageContext, checker); + } + + export function inferTypeForParametersFromReferences(references: Identifier[], declaration: FunctionLikeDeclaration, checker: TypeChecker, cancellationToken: CancellationToken): (Type | undefined)[] | undefined { + if (declaration.parameters) { + const usageContext: UsageContext = {}; + for (const reference of references) { + cancellationToken.throwIfCancellationRequested(); + inferTypeFromContext(reference, checker, usageContext); + } + const isConstructor = declaration.kind === SyntaxKind.Constructor; + const callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts; + if (callContexts) { + const paramTypes: Type[] = []; + for (let parameterIndex = 0; parameterIndex < declaration.parameters.length; parameterIndex++) { + let types: Type[] = []; + const isRestParameter = ts.isRestParameter(declaration.parameters[parameterIndex]); + for (const callContext of callContexts) { + if (callContext.argumentTypes.length > parameterIndex) { + if (isRestParameter) { + types = concatenate(types, map(callContext.argumentTypes.slice(parameterIndex), a => checker.getBaseTypeOfLiteralType(a))); + } + else { + types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex])); + } + } + } + if (types.length) { + const type = checker.getWidenedType(checker.getUnionType(types, /*subtypeReduction*/ true)); + paramTypes[parameterIndex] = isRestParameter ? checker.createArrayType(type) : type; + } + } + return paramTypes; + } + } + return undefined; + } + + function inferTypeFromContext(node: Expression, checker: TypeChecker, usageContext: UsageContext): void { + while (isRightSideOfQualifiedNameOrPropertyAccess(node)) { + node = node.parent; + } + + switch (node.parent.kind) { + case SyntaxKind.PostfixUnaryExpression: + usageContext.isNumber = true; + break; + case SyntaxKind.PrefixUnaryExpression: + inferTypeFromPrefixUnaryExpressionContext(node.parent, usageContext); + break; + case SyntaxKind.BinaryExpression: + inferTypeFromBinaryExpressionContext(node, node.parent, checker, usageContext); + break; + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + inferTypeFromSwitchStatementLabelContext(node.parent, checker, usageContext); + break; + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + if ((node.parent).expression === node) { + inferTypeFromCallExpressionContext(node.parent, checker, usageContext); + } + else { + inferTypeFromContextualType(node, checker, usageContext); + } + break; + case SyntaxKind.PropertyAccessExpression: + inferTypeFromPropertyAccessExpressionContext(node.parent, checker, usageContext); + break; + case SyntaxKind.ElementAccessExpression: + inferTypeFromPropertyElementExpressionContext(node.parent, node, checker, usageContext); + break; + default: + return inferTypeFromContextualType(node, checker, usageContext); + } + } + + function inferTypeFromContextualType(node: Expression, checker: TypeChecker, usageContext: UsageContext): void { + if (isPartOfExpression(node)) { + addCandidateType(usageContext, checker.getContextualType(node)); + } + } + + function inferTypeFromPrefixUnaryExpressionContext(node: PrefixUnaryExpression, usageContext: UsageContext): void { + switch (node.operator) { + case SyntaxKind.PlusPlusToken: + case SyntaxKind.MinusMinusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + usageContext.isNumber = true; + break; + + case SyntaxKind.PlusToken: + usageContext.isNumberOrString = true; + break; + + // case SyntaxKind.ExclamationToken: + // no inferences here; + } + } + + function inferTypeFromBinaryExpressionContext(node: Expression, parent: BinaryExpression, checker: TypeChecker, usageContext: UsageContext): void { + switch (parent.operatorToken.kind) { + // ExponentiationOperator + case SyntaxKind.AsteriskAsteriskToken: + + // MultiplicativeOperator + case SyntaxKind.AsteriskToken: + case SyntaxKind.SlashToken: + case SyntaxKind.PercentToken: + + // ShiftOperator + case SyntaxKind.LessThanLessThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + + // BitwiseOperator + case SyntaxKind.AmpersandToken: + case SyntaxKind.BarToken: + case SyntaxKind.CaretToken: + + // CompoundAssignmentOperator + case SyntaxKind.MinusEqualsToken: + case SyntaxKind.AsteriskAsteriskEqualsToken: + case SyntaxKind.AsteriskEqualsToken: + case SyntaxKind.SlashEqualsToken: + case SyntaxKind.PercentEqualsToken: + case SyntaxKind.AmpersandEqualsToken: + case SyntaxKind.BarEqualsToken: + case SyntaxKind.CaretEqualsToken: + case SyntaxKind.LessThanLessThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanEqualsToken: + + // AdditiveOperator + case SyntaxKind.MinusToken: + + // RelationalOperator + case SyntaxKind.LessThanToken: + case SyntaxKind.LessThanEqualsToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.GreaterThanEqualsToken: + const operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + if (operandType.flags & TypeFlags.EnumLike) { + addCandidateType(usageContext, operandType); + } + else { + usageContext.isNumber = true; + } + break; + + case SyntaxKind.PlusEqualsToken: + case SyntaxKind.PlusToken: + const otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + if (otherOperandType.flags & TypeFlags.EnumLike) { + addCandidateType(usageContext, otherOperandType); + } + else if (otherOperandType.flags & TypeFlags.NumberLike) { + usageContext.isNumber = true; + } + else if (otherOperandType.flags & TypeFlags.StringLike) { + usageContext.isString = true; + } + else { + usageContext.isNumberOrString = true; + } + break; + + // AssignmentOperators + case SyntaxKind.EqualsToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + addCandidateType(usageContext, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)); + break; + + case SyntaxKind.InKeyword: + if (node === parent.left) { + usageContext.isString = true; + } + break; + + // LogicalOperator + case SyntaxKind.BarBarToken: + if (node === parent.left && + (node.parent.parent.kind === SyntaxKind.VariableDeclaration || isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) { + // var x = x || {}; + // TODO: use getFalsyflagsOfType + addCandidateType(usageContext, checker.getTypeAtLocation(parent.right)); + } + break; + + case SyntaxKind.AmpersandAmpersandToken: + case SyntaxKind.CommaToken: + case SyntaxKind.InstanceOfKeyword: + // nothing to infer here + break; + } + } + + function inferTypeFromSwitchStatementLabelContext(parent: CaseOrDefaultClause, checker: TypeChecker, usageContext: UsageContext): void { + addCandidateType(usageContext, checker.getTypeAtLocation((parent.parent.parent).expression)); + } + + function inferTypeFromCallExpressionContext(parent: CallExpression | NewExpression, checker: TypeChecker, usageContext: UsageContext): void { + const callContext: CallContext = { + argumentTypes: [], + returnType: {} + }; + + if (parent.arguments) { + for (const argument of parent.arguments) { + callContext.argumentTypes.push(checker.getTypeAtLocation(argument)); + } + } + + inferTypeFromContext(parent, checker, callContext.returnType); + if (parent.kind === SyntaxKind.CallExpression) { + (usageContext.callContexts || (usageContext.callContexts = [])).push(callContext); + } + else { + (usageContext.constructContexts || (usageContext.constructContexts = [])).push(callContext); + } + } + + function inferTypeFromPropertyAccessExpressionContext(parent: PropertyAccessExpression, checker: TypeChecker, usageContext: UsageContext): void { + const name = escapeLeadingUnderscores(parent.name.text); + if (!usageContext.properties) { + usageContext.properties = createUnderscoreEscapedMap(); + } + const propertyUsageContext = {}; + inferTypeFromContext(parent, checker, propertyUsageContext); + usageContext.properties.set(name, propertyUsageContext); + } + + function inferTypeFromPropertyElementExpressionContext(parent: ElementAccessExpression, node: Expression, checker: TypeChecker, usageContext: UsageContext): void { + if (node === parent.argumentExpression) { + usageContext.isNumberOrString = true; + return; + } + else { + const indexType = checker.getTypeAtLocation(parent); + const indexUsageContext = {}; + inferTypeFromContext(parent, checker, indexUsageContext); + if (indexType.flags & TypeFlags.NumberLike) { + usageContext.numberIndexContext = indexUsageContext; + } + else { + usageContext.stringIndexContext = indexUsageContext; + } + } + } + + function getTypeFromUsageContext(usageContext: UsageContext, checker: TypeChecker): Type | undefined { + if (usageContext.isNumberOrString && !usageContext.isNumber && !usageContext.isString) { + return checker.getUnionType([checker.getNumberType(), checker.getStringType()]); + } + else if (usageContext.isNumber) { + return checker.getNumberType(); + } + else if (usageContext.isString) { + return checker.getStringType(); + } + else if (usageContext.candidateTypes) { + return checker.getWidenedType(checker.getUnionType(map(usageContext.candidateTypes, t => checker.getBaseTypeOfLiteralType(t)), /*subtypeReduction*/ true)); + } + else if (usageContext.properties && hasCallContext(usageContext.properties.get("then" as __String))) { + const paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then" as __String).callContexts, /*isRestParameter*/ false, checker); + const types = paramType.getCallSignatures().map(c => c.getReturnType()); + return checker.createPromiseType(types.length ? checker.getUnionType(types, /*subtypeReduction*/ true) : checker.getAnyType()); + } + else if (usageContext.properties && hasCallContext(usageContext.properties.get("push" as __String))) { + return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push" as __String).callContexts, /*isRestParameter*/ false, checker)); + } + else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) { + const members = createUnderscoreEscapedMap(); + const callSignatures: Signature[] = []; + const constructSignatures: Signature[] = []; + let stringIndexInfo: IndexInfo; + let numberIndexInfo: IndexInfo; + + if (usageContext.properties) { + usageContext.properties.forEach((context, name) => { + const symbol = checker.createSymbol(SymbolFlags.Property, name); + symbol.type = getTypeFromUsageContext(context, checker); + members.set(name, symbol); + }); + } + + if (usageContext.callContexts) { + for (const callContext of usageContext.callContexts) { + callSignatures.push(getSignatureFromCallContext(callContext, checker)); + } + } + + if (usageContext.constructContexts) { + for (const constructContext of usageContext.constructContexts) { + constructSignatures.push(getSignatureFromCallContext(constructContext, checker)); + } + } + + if (usageContext.numberIndexContext) { + numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false); + } + + if (usageContext.stringIndexContext) { + stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false); + } + + return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + } + else { + return undefined; + } + } + + function getParameterTypeFromCallContexts(parameterIndex: number, callContexts: CallContext[], isRestParameter: boolean, checker: TypeChecker) { + let types: Type[] = []; + if (callContexts) { + for (const callContext of callContexts) { + if (callContext.argumentTypes.length > parameterIndex) { + if (isRestParameter) { + types = concatenate(types, map(callContext.argumentTypes.slice(parameterIndex), a => checker.getBaseTypeOfLiteralType(a))); + } + else { + types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex])); + } + } + } + } + + if (types.length) { + const type = checker.getWidenedType(checker.getUnionType(types, /*subtypeReduction*/ true)); + return isRestParameter ? checker.createArrayType(type) : type; + } + return undefined; + } + + function getSignatureFromCallContext(callContext: CallContext, checker: TypeChecker): Signature { + const parameters: Symbol[] = []; + for (let i = 0; i < callContext.argumentTypes.length; i++) { + const symbol = checker.createSymbol(SymbolFlags.FunctionScopedVariable, escapeLeadingUnderscores(`arg${i}`)); + symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i])); + parameters.push(symbol); + } + const returnType = getTypeFromUsageContext(callContext.returnType, checker); + return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + } + + function addCandidateType(context: UsageContext, type: Type) { + if (type && !(type.flags & TypeFlags.Any) && !(type.flags & TypeFlags.Never)) { + (context.candidateTypes || (context.candidateTypes = [])).push(type); + } + } + + function hasCallContext(usageContext: UsageContext) { + return usageContext && usageContext.callContexts; + } + } +} diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b1595030df088..82c593d8d424b 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3068,6 +3068,8 @@ declare namespace ts { function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node: Node): boolean; + function isSetAccessor(node: Node): node is SetAccessorDeclaration; + function isGetAccessor(node: Node): node is GetAccessorDeclaration; } declare namespace ts { interface ErrorCallback { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0c74f74c7413c..14fae7d0d77a0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3123,6 +3123,8 @@ declare namespace ts { function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node: Node): boolean; + function isSetAccessor(node: Node): node is SetAccessorDeclaration; + function isGetAccessor(node: Node): node is GetAccessorDeclaration; } declare namespace ts { function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; diff --git a/tests/cases/fourslash/codeFixInferFromUsage.ts b/tests/cases/fourslash/codeFixInferFromUsage.ts new file mode 100644 index 0000000000000..5de8d98979994 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsage.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +////[|var foo;|] +////function f() { +//// foo += 2; +////} + +verify.rangeAfterCodeFix("var foo: number;",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageGetter.ts b/tests/cases/fourslash/codeFixInferFromUsageGetter.ts new file mode 100644 index 0000000000000..f83eed1432d49 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageGetter.ts @@ -0,0 +1,10 @@ +/// + +// @noImplicitAny: true +////declare class C { +//// [|get x();|] +////} +////} +////(new C).x = 1; + +verify.rangeAfterCodeFix("get x(): number;", undefined, undefined, 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageGetter2.ts b/tests/cases/fourslash/codeFixInferFromUsageGetter2.ts new file mode 100644 index 0000000000000..a50d471ad12d3 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageGetter2.ts @@ -0,0 +1,11 @@ +/// + +// @noImplicitAny: true +////class C { +//// [|get x() |]{ +//// return undefined; +//// } +////} +////(new C).x = 1; + +verify.rangeAfterCodeFix("get x(): number", undefined, undefined, 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageInaccessibleTypes.ts b/tests/cases/fourslash/codeFixInferFromUsageInaccessibleTypes.ts new file mode 100644 index 0000000000000..ae9106be8c4f0 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageInaccessibleTypes.ts @@ -0,0 +1,20 @@ +/// + +// @noImplicitAny: true +////function f1([|a |]) { } +////function h1() { +//// class C { p: number }; +//// f1({ ofTypeC: new C() }); +////} +//// +////function f2([|a |]) { } +////function h2() { +//// interface I { a: number } +//// var i: I = {a : 1}; +//// f2(i); +//// f2(2); +//// f2(false); +////} +//// + +verify.not.codeFixAvailable(); diff --git a/tests/cases/fourslash/codeFixInferFromUsageMember.ts b/tests/cases/fourslash/codeFixInferFromUsageMember.ts new file mode 100644 index 0000000000000..c82542e5e3f25 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageMember.ts @@ -0,0 +1,11 @@ +/// + +// @noImplicitAny: true +////class C { +//// [|p;|] +//// method() { +//// this.p.push(10); +//// } +////} + +verify.rangeAfterCodeFix("p: number[];"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageMember2.ts b/tests/cases/fourslash/codeFixInferFromUsageMember2.ts new file mode 100644 index 0000000000000..486112935eefd --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageMember2.ts @@ -0,0 +1,10 @@ +/// + +// @noImplicitAny: true +////interface I { +//// [|p;|] +////} +////var i: I; +////i.p = 0; + +verify.rangeAfterCodeFix("p: number;"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageMember3.ts b/tests/cases/fourslash/codeFixInferFromUsageMember3.ts new file mode 100644 index 0000000000000..49f2cb66c18cd --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageMember3.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +////class C { +//// constructor([|public p)|] { } +////} +////new C("string"); + +verify.rangeAfterCodeFix("public p: string)"); diff --git a/tests/cases/fourslash/codeFixInferFromUsageMultipleParameters.ts b/tests/cases/fourslash/codeFixInferFromUsageMultipleParameters.ts new file mode 100644 index 0000000000000..89e2c935e876f --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageMultipleParameters.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +//// function f([|a, b, c, d: number, e = 0, ...d |]) { +//// } +//// f(1, "string", { a: 1 }, {shouldNotBeHere: 2}, {shouldNotBeHere: 2}, 3, "string"); + + +verify.rangeAfterCodeFix("a: number, b: string, c: { a: number; }, d: number, e = 0, ...d: (string | number)[]", /*includeWhiteSpace*/ false, /*errorCode*/ undefined, /*index*/ 1); diff --git a/tests/cases/fourslash/codeFixInferFromUsageOptionalParam.ts b/tests/cases/fourslash/codeFixInferFromUsageOptionalParam.ts new file mode 100644 index 0000000000000..f10de4bb03ae8 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageOptionalParam.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +////function f([|a? |]){ +////} +////f(); +////f(1); + +verify.rangeAfterCodeFix("a?: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageOptionalParam2.ts b/tests/cases/fourslash/codeFixInferFromUsageOptionalParam2.ts new file mode 100644 index 0000000000000..2ca820e0327c0 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageOptionalParam2.ts @@ -0,0 +1,8 @@ +/// + +// @noImplicitAny: true +////function f([|a? |]){ +//// if (a < 9) return; +////} + +verify.rangeAfterCodeFix("a?: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageRestParam.ts b/tests/cases/fourslash/codeFixInferFromUsageRestParam.ts new file mode 100644 index 0000000000000..963f84d651530 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageRestParam.ts @@ -0,0 +1,11 @@ +/// + +// @noImplicitAny: true +////function f(a: number, [|...rest |]){ +////} +////f(1); +////f(2, "s1"); +////f(3, "s1", "s2"); +////f(3, "s1", "s2", "s3", "s4"); + +verify.rangeAfterCodeFix("...rest: string[]"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageRestParam2.ts b/tests/cases/fourslash/codeFixInferFromUsageRestParam2.ts new file mode 100644 index 0000000000000..ae8262402281e --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageRestParam2.ts @@ -0,0 +1,11 @@ +/// + +// @noImplicitAny: true +////function f(a: number, [|...rest |]){ +////} +////f(1); +////f(2, "s1"); +////f(3, false, "s2"); +////f(4, "s1", "s2", false, "s4"); + +verify.rangeAfterCodeFix("...rest: (string | boolean)[]"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageRestParam3.ts b/tests/cases/fourslash/codeFixInferFromUsageRestParam3.ts new file mode 100644 index 0000000000000..4752176a324a2 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageRestParam3.ts @@ -0,0 +1,8 @@ +/// + +// @noImplicitAny: true +////function f(a: number, [|...rest |]){ +//// rest.push(22); +////} + +verify.rangeAfterCodeFix("...rest: number[]"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageSetter.ts b/tests/cases/fourslash/codeFixInferFromUsageSetter.ts new file mode 100644 index 0000000000000..f515cd5a90687 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageSetter.ts @@ -0,0 +1,10 @@ +/// + +// @noImplicitAny: true +////class C { +//// set [|x(v)|] { +//// } +////} +////(new C).x = 1; + +verify.rangeAfterCodeFix("x(v: number)", undefined, undefined, 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageSetter2.ts b/tests/cases/fourslash/codeFixInferFromUsageSetter2.ts new file mode 100644 index 0000000000000..a1169a03df16b --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageSetter2.ts @@ -0,0 +1,10 @@ +/// + +// @noImplicitAny: true +////class C { +//// set [|x(v)|] { +//// } +////} +////(new C).x = 1; + +verify.rangeAfterCodeFix("x(v: number)", undefined, undefined, 1); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageVariable.ts b/tests/cases/fourslash/codeFixInferFromUsageVariable.ts new file mode 100644 index 0000000000000..f89b8c867f9d4 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageVariable.ts @@ -0,0 +1,9 @@ +/// + +// @noImplicitAny: true +////[|var x;|] +////function f() { +//// x++; +////} + +verify.rangeAfterCodeFix("var x: number;", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsageVariable2.ts b/tests/cases/fourslash/codeFixInferFromUsageVariable2.ts new file mode 100644 index 0000000000000..bf8e2bb07e54d --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageVariable2.ts @@ -0,0 +1,13 @@ +/// + +// @noImplicitAny: true +////[|var x; +////function f() { +//// x++; +////}|] + +verify.rangeAfterCodeFix(`var x: number; +function f() { + x++; +} +`, /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 1); \ No newline at end of file From 27b4417304cebfc6fe22aeb747c0dca368ed906f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 10:38:02 -0700 Subject: [PATCH 149/246] Assert:checkTypeArguments isn't passed too many type arguments --- src/compiler/checker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3380e89cd0f56..3b6ef850ce80d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15649,6 +15649,7 @@ namespace ts { const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); let mapper: TypeMapper; for (let i = 0; i < typeArgumentNodes.length; i++) { + Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments"); const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (!constraint) continue; From 4de6b0dd2d104754ddca97d3c03e1819e0793668 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 12 Oct 2017 11:34:34 -0700 Subject: [PATCH 150/246] Introduce and consume suppressLeadingAndTrailingTrivia Fixes #18626 --- src/compiler/factory.ts | 10 ++++++ src/harness/unittests/extractConstants.ts | 8 +++++ src/harness/unittests/extractFunctions.ts | 8 +++++ src/services/refactors/extractSymbol.ts | 18 +++++----- src/services/utilities.ts | 35 +++++++++++++++++++ .../extractConstant_PreserveTrivia.js | 17 +++++++++ .../extractConstant_PreserveTrivia.ts | 17 +++++++++ .../extractFunction/extractFunction13.ts | 6 ++-- .../extractFunction_PreserveTrivia.js | 19 ++++++++++ .../extractFunction_PreserveTrivia.ts | 19 ++++++++++ .../fourslash/extract-method-uniqueName.ts | 5 ++- 11 files changed, 146 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.js create mode 100644 tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.ts create mode 100644 tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js create mode 100644 tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index fe183c5e8060c..65c1c92f36652 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2612,6 +2612,16 @@ namespace ts { return node; } + /** + * Sets flags that control emit behavior of a node. + */ + /* @internal */ + export function addEmitFlags(node: T, emitFlags: EmitFlags) { + const emitNode = getOrCreateEmitNode(node); + emitNode.flags = emitNode.flags | emitFlags; + return node; + } + /** * Gets a custom text range to use when emitting source maps. */ diff --git a/src/harness/unittests/extractConstants.ts b/src/harness/unittests/extractConstants.ts index 09f8db34f31fe..61ffbd01a639b 100644 --- a/src/harness/unittests/extractConstants.ts +++ b/src/harness/unittests/extractConstants.ts @@ -223,6 +223,14 @@ const f = () => { testExtractConstant("extractConstant_ArrowFunction_Expression", `const f = () => [#|2 + 1|];`); + testExtractConstant("extractConstant_PreserveTrivia", ` +// a +var q = /*b*/ //c + /*d*/ [#|1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2|] /*k*/ //l + /*m*/; /*n*/ //o`); + testExtractConstantFailed("extractConstant_Void", ` function f(): void { } [#|f();|]`); diff --git a/src/harness/unittests/extractFunctions.ts b/src/harness/unittests/extractFunctions.ts index c69026c0be8af..789882ffd5091 100644 --- a/src/harness/unittests/extractFunctions.ts +++ b/src/harness/unittests/extractFunctions.ts @@ -532,6 +532,14 @@ function f() { [#|let x;|] return { x }; }`); + + testExtractFunction("extractFunction_PreserveTrivia", ` +// a +var q = /*b*/ //c + /*d*/ [#|1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2|] /*k*/ //l + /*m*/; /*n*/ //o`); }); function testExtractFunction(caption: string, text: string) { diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 9dd148e5420fa..715b42b6bc89a 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -740,6 +740,8 @@ namespace ts.refactor.extractSymbol { } const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); + suppressLeadingAndTrailingTrivia(body); + let newFunction: MethodDeclaration | FunctionDeclaration; if (isClassLike(scope)) { @@ -926,15 +928,10 @@ namespace ts.refactor.extractSymbol { } } - if (isReadonlyArray(range.range)) { - changeTracker.replaceNodesWithNodes(context.file, range.range, newNodes, { - nodeSeparator: context.newLineCharacter, - suffix: context.newLineCharacter // insert newline only when replacing statements - }); - } - else { - changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes, { nodeSeparator: context.newLineCharacter }); - } + const replacementRange = isReadonlyArray(range.range) + ? { pos: first(range.range).getStart(), end: last(range.range).end } + : { pos: range.range.getStart(), end: range.range.end }; + changeTracker.replaceRangeWithNodes(context.file, replacementRange, newNodes, { nodeSeparator: context.newLineCharacter }); const edits = changeTracker.getChanges(); const renameRange = isReadonlyArray(range.range) ? first(range.range) : range.range; @@ -982,6 +979,7 @@ namespace ts.refactor.extractSymbol { : checker.typeToTypeNode(checker.getContextualType(node), scope, NodeBuilderFlags.NoTruncation); const initializer = transformConstantInitializer(node, substitutions); + suppressLeadingAndTrailingTrivia(initializer); const changeTracker = textChanges.ChangeTracker.fromContext(context); @@ -1014,7 +1012,7 @@ namespace ts.refactor.extractSymbol { changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, { suffix: context.newLineCharacter + context.newLineCharacter }); // Consume - changeTracker.replaceNodeWithNodes(context.file, node, [localReference], { nodeSeparator: context.newLineCharacter }); + changeTracker.replaceRange(context.file, { pos: node.getStart(), end: node.end }, localReference); } else { const newVariableDeclaration = createVariableDeclaration(localNameText, variableType, initializer); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 0eb3f88cc9a77..df3f3c5c6b489 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1369,4 +1369,39 @@ namespace ts { return visited; } + + /** + * Sets EmitFlags to suppress leading and trailing trivia on the node. + */ + /* @internal */ + export function suppressLeadingAndTrailingTrivia(node: Node) { + Debug.assert(node !== undefined); + + suppressLeading(node); + suppressTrailing(node); + + function suppressLeading(node: Node) { + addEmitFlags(node, EmitFlags.NoLeadingComments); + + const firstChild = forEachChild(node, child => child); + firstChild && suppressLeading(firstChild); + } + + function suppressTrailing(node: Node) { + addEmitFlags(node, EmitFlags.NoTrailingComments); + + let lastChild: Node = undefined; + forEachChild( + node, + child => (lastChild = child, undefined), + children => { + // As an optimization, jump straight to the end of the list. + if (children.length) { + lastChild = last(children); + } + return undefined; + }); + lastChild && suppressTrailing(lastChild); + } + } } diff --git a/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.js b/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.js new file mode 100644 index 0000000000000..22abb77901d68 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.js @@ -0,0 +1,17 @@ +// ==ORIGINAL== + +// a +var q = /*b*/ //c + /*d*/ /*[#|*/1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2/*|]*/ /*k*/ //l + /*m*/; /*n*/ //o +// ==SCOPE::Extract to constant in enclosing scope== +const newLocal = 1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2; + +// a +var q = /*b*/ //c + /*d*/ /*RENAME*/newLocal /*k*/ //l + /*m*/; /*n*/ //o \ No newline at end of file diff --git a/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.ts b/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.ts new file mode 100644 index 0000000000000..22abb77901d68 --- /dev/null +++ b/tests/baselines/reference/extractConstant/extractConstant_PreserveTrivia.ts @@ -0,0 +1,17 @@ +// ==ORIGINAL== + +// a +var q = /*b*/ //c + /*d*/ /*[#|*/1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2/*|]*/ /*k*/ //l + /*m*/; /*n*/ //o +// ==SCOPE::Extract to constant in enclosing scope== +const newLocal = 1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2; + +// a +var q = /*b*/ //c + /*d*/ /*RENAME*/newLocal /*k*/ //l + /*m*/; /*n*/ //o \ No newline at end of file diff --git a/tests/baselines/reference/extractFunction/extractFunction13.ts b/tests/baselines/reference/extractFunction/extractFunction13.ts index 4987039d5dac3..662701ebf415a 100644 --- a/tests/baselines/reference/extractFunction/extractFunction13.ts +++ b/tests/baselines/reference/extractFunction/extractFunction13.ts @@ -20,7 +20,7 @@ (u2a: U2a, u2b: U2b) => { function F2(t2a: T2a, t2b: T2b) { (u3a: U3a, u3b: U3b) => { - /*RENAME*/newFunction(u3a); + /*RENAME*/newFunction(u3a); } function newFunction(u3a: U3a) { @@ -40,7 +40,7 @@ (u2a: U2a, u2b: U2b) => { function F2(t2a: T2a, t2b: T2b) { (u3a: U3a, u3b: U3b) => { - /*RENAME*/newFunction(t2a, u2a, u3a); + /*RENAME*/newFunction(t2a, u2a, u3a); } } } @@ -60,7 +60,7 @@ (u2a: U2a, u2b: U2b) => { function F2(t2a: T2a, t2b: T2b) { (u3a: U3a, u3b: U3b) => { - /*RENAME*/newFunction(t1a, t2a, u1a, u2a, u3a); + /*RENAME*/newFunction(t1a, t2a, u1a, u2a, u3a); } } } diff --git a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js new file mode 100644 index 0000000000000..b5e4bc76c6e2f --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +// a +var q = /*b*/ //c + /*d*/ /*[#|*/1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2/*|]*/ /*k*/ //l + /*m*/; /*n*/ //o +// ==SCOPE::Extract to function in global scope== + +// a +var q = /*b*/ //c + /*d*/ /*RENAME*/newFunction() /*k*/ //l + /*m*/; /*n*/ //o +function newFunction() { + return 1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2; +} diff --git a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts new file mode 100644 index 0000000000000..b5e4bc76c6e2f --- /dev/null +++ b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +// a +var q = /*b*/ //c + /*d*/ /*[#|*/1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2/*|]*/ /*k*/ //l + /*m*/; /*n*/ //o +// ==SCOPE::Extract to function in global scope== + +// a +var q = /*b*/ //c + /*d*/ /*RENAME*/newFunction() /*k*/ //l + /*m*/; /*n*/ //o +function newFunction() { + return 1 /*e*/ //f + /*g*/ + /*h*/ //i + /*j*/ 2; +} diff --git a/tests/cases/fourslash/extract-method-uniqueName.ts b/tests/cases/fourslash/extract-method-uniqueName.ts index 4271d9e84d2f2..da4c68cfb7e1d 100644 --- a/tests/cases/fourslash/extract-method-uniqueName.ts +++ b/tests/cases/fourslash/extract-method-uniqueName.ts @@ -11,10 +11,9 @@ edit.applyRefactor({ actionName: "function_scope_0", actionDescription: "Extract to function in global scope", newContent: -`/*RENAME*/newFunction_1(); - +`// newFunction +/*RENAME*/newFunction_1(); function newFunction_1() { - // newFunction 1 + 1; } ` From 123347d5c42390068325590f348b4e7be3b78f87 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 11:40:07 -0700 Subject: [PATCH 151/246] Convert @template tag to type parameters in refactor --- src/compiler/utilities.ts | 16 ++++++------ .../refactors/annotateWithTypeFromJSDoc.ts | 25 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2c1e25f74afd4..c4d3de453ba5c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2700,11 +2700,11 @@ namespace ts { * Gets the effective type annotation of a variable, parameter, or property. If the node was * parsed in a JavaScript file, gets the type annotation from JSDoc. */ - export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode | undefined { + export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration, checkJSDoc?: boolean): TypeNode | undefined { if (node.type) { return node.type; } - if (isInJavaScriptFile(node)) { + if (checkJSDoc || isInJavaScriptFile(node)) { return getJSDocType(node); } } @@ -2713,11 +2713,11 @@ namespace ts { * Gets the effective return type annotation of a signature. If the node was parsed in a * JavaScript file, gets the return type annotation from JSDoc. */ - export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode | undefined { + export function getEffectiveReturnTypeNode(node: SignatureDeclaration, checkJSDoc?: boolean): TypeNode | undefined { if (node.type) { return node.type; } - if (isInJavaScriptFile(node)) { + if (checkJSDoc || isInJavaScriptFile(node)) { return getJSDocReturnType(node); } } @@ -2726,11 +2726,11 @@ namespace ts { * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. */ - export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray { + export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters, checkJSDoc?: boolean): ReadonlyArray { if (node.typeParameters) { return node.typeParameters; } - if (isInJavaScriptFile(node)) { + if (checkJSDoc || isInJavaScriptFile(node)) { const templateTag = getJSDocTemplateTag(node); return templateTag && templateTag.typeParameters; } @@ -2740,9 +2740,9 @@ namespace ts { * Gets the effective type annotation of the value parameter of a set accessor. If the node * was parsed in a JavaScript file, gets the type annotation from JSDoc. */ - export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode { + export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration, checkJSDoc?: boolean): TypeNode { const parameter = getSetAccessorValueParameter(node); - return parameter && getEffectiveTypeAnnotationNode(parameter); + return parameter && getEffectiveTypeAnnotationNode(parameter, checkJSDoc); } export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray) { diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 529793b7cd1cb..bc6dcd073bf49 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -31,11 +31,11 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); - const decl = findAncestor(node, isTypedNode); + const decl = findAncestor(node, isDeclarationWithType); if (decl && !decl.type) { const type = getJSDocType(decl); - const returnType = getJSDocReturnType(decl); - const annotate = (returnType || type && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : + const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); + const annotate = (isFunctionWithJSDoc || type && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : type ? annotateTypeFromJSDoc : undefined; if (annotate) { @@ -61,7 +61,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); - const decl = findAncestor(token, isTypedNode); + const decl = findAncestor(token, isDeclarationWithType); const jsdocType = getJSDocReturnType(decl) || getJSDocType(decl); if (!decl || !jsdocType || decl.type) { Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); @@ -95,7 +95,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { }; } - function isTypedNode(node: Node): node is DeclarationWithType { + function isDeclarationWithType(node: Node): node is DeclarationWithType { return isFunctionLikeDeclaration(node) || node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.Parameter || @@ -104,22 +104,23 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } function addTypesToFunctionLike(decl: FunctionLikeDeclaration) { - const returnType = decl.type || transformJSDocType(getJSDocReturnType(decl)) as TypeNode; + const typeParameters = getEffectiveTypeParameterDeclarations(decl, /*checkJSDoc*/ true); const parameters = decl.parameters.map( - p => createParameter(p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || transformJSDocType(getJSDocType(p)) as TypeNode, p.initializer)); + p => createParameter(p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, transformJSDocType(getEffectiveTypeAnnotationNode(p, /*checkJSDoc*/ true)) as TypeNode, p.initializer)); + const returnType = transformJSDocType(getEffectiveReturnTypeNode(decl, /*checkJSDoc*/ true)) as TypeNode; switch (decl.kind) { case SyntaxKind.FunctionDeclaration: - return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.typeParameters, parameters, returnType, decl.body); + return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, typeParameters, parameters, returnType, decl.body); case SyntaxKind.Constructor: return createConstructor(decl.decorators, decl.modifiers, parameters, decl.body); case SyntaxKind.FunctionExpression: - return createFunctionExpression(decl.modifiers, decl.asteriskToken, (decl as FunctionExpression).name, decl.typeParameters, parameters, returnType, decl.body); + return createFunctionExpression(decl.modifiers, decl.asteriskToken, (decl as FunctionExpression).name, typeParameters, parameters, returnType, decl.body); case SyntaxKind.ArrowFunction: - return createArrowFunction(decl.modifiers, decl.typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body); + return createArrowFunction(decl.modifiers, typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body); case SyntaxKind.MethodDeclaration: - return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, decl.typeParameters, parameters, returnType, decl.body); + return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, typeParameters, parameters, returnType, decl.body); case SyntaxKind.GetAccessor: - return createGetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, returnType, decl.body); + return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, returnType, decl.body); case SyntaxKind.SetAccessor: return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body); default: From b440d75bc427636211c46eb2b1140d51af34820a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 11:40:40 -0700 Subject: [PATCH 152/246] Test refactor of JSDoc @template tag --- .../fourslash/annotateWithTypeFromJSDoc19.ts | 19 +++++++++++++++++++ .../fourslash/annotateWithTypeFromJSDoc20.ts | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts new file mode 100644 index 0000000000000..9e7ef6d25fd63 --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts @@ -0,0 +1,19 @@ +/// +// @strict: true +/////** +//// * @template T +//// * @param {number} a +//// * @param {T} b +//// */ +////function /*1*/f(a, b) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @template T + * @param {number} a + * @param {T} b + */ +function f(a: number, b: T) { +}`, 'Annotate with types from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts new file mode 100644 index 0000000000000..a45eb788c738c --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts @@ -0,0 +1,17 @@ +/// +// @strict: true +/////** +//// * @param {number} a +//// * @param {T} b +//// */ +////function /*1*/f(a, b) { +////} + +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @param {number} a + * @param {T} b + */ +function f(a: number, b: T) { +}`, 'Annotate with types from JSDoc', 'annotate'); From 412e31b8bc99472c17641bb12f65efd349a93cb8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Oct 2017 17:10:45 -0700 Subject: [PATCH 153/246] Adding test case where opened file included in project is not added to ref count of configured project --- .../unittests/tsserverProjectSystem.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 236f52db1347a..40eef501e52b1 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -335,6 +335,10 @@ namespace ts.projectSystem { return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } + function checkOpenFiles(projectService: server.ProjectService, expectedFiles: FileOrFolder[]) { + checkFileNames("Open files", projectService.openFiles.map(info => info.fileName), expectedFiles.map(file => file.path)); + } + /** * Test server cancellation token used to mock host token cancellation requests. * The cancelAfterRequest constructor param specifies how many isCancellationRequested() calls @@ -2109,6 +2113,90 @@ namespace ts.projectSystem { assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 5"); }); + it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { + const file1 = { + path: "/a/b/src/file1.ts", + content: "let x = 1;" + }; + const file2 = { + path: "/a/b/src/file2.ts", + content: "let y = 1;" + }; + const file3 = { + path: "/a/b/file3.ts", + content: "let z = 1;" + }; + const file4 = { + path: "/a/file4.ts", + content: "let z = 1;" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ files: ["src/file1.ts", "file3.ts"] }) + }; + + const files = [file1, file2, file3, file4]; + const host = createServerHost(files.concat(configFile)); + const projectService = createProjectService(host); + + projectService.openClientFile(file1.path); + projectService.openClientFile(file2.path); + projectService.openClientFile(file3.path); + projectService.openClientFile(file4.path); + + const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)); + checkOpenFiles(projectService, files); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + const configProject1 = projectService.configuredProjects.get(configFile.path); + assert.equal(configProject1.openRefCount, 2); + checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); + const inferredProject1 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject1, [file2.path]); + const inferredProject2 = projectService.inferredProjects[1]; + checkProjectActualFiles(inferredProject2, [file4.path]); + + configFile.content = "{}"; + host.reloadFS(files.concat(configFile)); + host.runQueuedTimeoutCallbacks(); + + verifyScriptInfos(); + checkOpenFiles(projectService, files); + verifyConfiguredProjectStateAfterUpdate(3); + checkNumberOfInferredProjects(projectService, 1); + const inferredProject3 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject3, [file4.path]); + assert.strictEqual(inferredProject2, inferredProject3); + + projectService.closeClientFile(file1.path); + projectService.closeClientFile(file2.path); + projectService.closeClientFile(file4.path); + + verifyScriptInfos(); + checkOpenFiles(projectService, [file3]); + verifyConfiguredProjectStateAfterUpdate(1); + checkNumberOfInferredProjects(projectService, 0); + + projectService.openClientFile(file4.path); + //verifyScriptInfos(); + checkOpenFiles(projectService, [file3, file4]); + //verifyConfiguredProjectStateAfterUpdate(1); + checkNumberOfInferredProjects(projectService, 1); + const inferredProject4 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject4, [file4.path]); + + function verifyScriptInfos() { + infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); + } + + function verifyConfiguredProjectStateAfterUpdate(_openRefCount: number) { + checkNumberOfConfiguredProjects(projectService, 1); + const configProject2 = projectService.configuredProjects.get(configFile.path); + assert.strictEqual(configProject1, configProject2); + checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); + //assert.equal(configProject2.openRefCount, openRefCount); + } + }); + it("language service disabled state is updated in external projects", () => { const f1 = { path: "/a/app.js", From b68a6363480409067e244da35b1372868947e17b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Oct 2017 11:48:25 -0700 Subject: [PATCH 154/246] Fix the way configured project's reference is managed so that the open file --- .../unittests/tsserverProjectSystem.ts | 186 +++++++++++++++--- src/server/editorServices.ts | 55 +++--- src/server/project.ts | 48 +++-- .../reference/api/tsserverlibrary.d.ts | 10 +- 4 files changed, 224 insertions(+), 75 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 40eef501e52b1..dfed47084e07e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1053,16 +1053,19 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path); + assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No open files + assert.isFalse(project.isClosed()); projectService.openClientFile(file2.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // file2 + assert.isFalse(project.isClosed()); }); it("should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", () => { @@ -1084,14 +1087,18 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path); + assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); projectService.openClientFile(libFile.path); checkNumberOfConfiguredProjects(projectService, 0); + assert.isFalse(project.hasOpenRef()); // No files + project closed + assert.isTrue(project.isClosed()); }); it("should not close external project with no open files", () => { @@ -2078,55 +2085,64 @@ namespace ts.projectSystem { projectService.openClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project1 = projectService.configuredProjects.get(tsconfig1.path); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 1"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 1"); // file2 assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, "containing projects count"); + assert.isFalse(project1.isClosed()); projectService.openClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 2, "Open ref count in project1 - 2"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 2"); // file2 assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); + assert.isFalse(project1.isClosed()); const project2 = projectService.configuredProjects.get(tsconfig2.path); - assert.equal(project2.openRefCount, 1, "Open ref count in project2 - 2"); + assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 2"); // file1 + assert.isFalse(project2.isClosed()); assert.equal(project1.getScriptInfo(file1.path).containingProjects.length, 2, `${file1.path} containing projects count`); assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, `${file2.path} containing projects count`); projectService.closeClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 3"); - assert.equal(project2.openRefCount, 1, "Open ref count in project2 - 3"); + assert.isFalse(project1.hasOpenRef(), "Has open ref count in project1 - 3"); // No files + assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 3"); // file1 assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.strictEqual(projectService.configuredProjects.get(tsconfig2.path), project2); + assert.isFalse(project1.isClosed()); + assert.isFalse(project2.isClosed()); projectService.closeClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 0, "Open ref count in project1 - 4"); - assert.equal(project2.openRefCount, 0, "Open ref count in project2 - 4"); + assert.isFalse(project1.hasOpenRef(), "Has open ref count in project1 - 4"); // No files + assert.isFalse(project2.hasOpenRef(), "Has open ref count in project2 - 4"); // No files assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.strictEqual(projectService.configuredProjects.get(tsconfig2.path), project2); + assert.isFalse(project1.isClosed()); + assert.isFalse(project2.isClosed()); projectService.openClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.isUndefined(projectService.configuredProjects.get(tsconfig2.path)); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 5"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 5"); // file2 + assert.isFalse(project1.isClosed()); + assert.isTrue(project2.isClosed()); }); it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { - const file1 = { + const file1: FileOrFolder = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2 = { + const file2: FileOrFolder = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3 = { + const file3: FileOrFolder = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4 = { + const file4: FileOrFolder = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -2148,7 +2164,7 @@ namespace ts.projectSystem { checkOpenFiles(projectService, files); checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); const configProject1 = projectService.configuredProjects.get(configFile.path); - assert.equal(configProject1.openRefCount, 2); + assert.isTrue(configProject1.hasOpenRef()); // file1 and file3 checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject1, [file2.path]); @@ -2161,11 +2177,11 @@ namespace ts.projectSystem { verifyScriptInfos(); checkOpenFiles(projectService, files); - verifyConfiguredProjectStateAfterUpdate(3); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file1, file2, file3 checkNumberOfInferredProjects(projectService, 1); const inferredProject3 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject3, [file4.path]); - assert.strictEqual(inferredProject2, inferredProject3); + assert.strictEqual(inferredProject3, inferredProject2); projectService.closeClientFile(file1.path); projectService.closeClientFile(file2.path); @@ -2173,30 +2189,122 @@ namespace ts.projectSystem { verifyScriptInfos(); checkOpenFiles(projectService, [file3]); - verifyConfiguredProjectStateAfterUpdate(1); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file3 checkNumberOfInferredProjects(projectService, 0); projectService.openClientFile(file4.path); - //verifyScriptInfos(); + verifyScriptInfos(); checkOpenFiles(projectService, [file3, file4]); - //verifyConfiguredProjectStateAfterUpdate(1); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file3 checkNumberOfInferredProjects(projectService, 1); const inferredProject4 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject4, [file4.path]); + projectService.closeClientFile(file3.path); + verifyScriptInfos(); + checkOpenFiles(projectService, [file4]); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ false); // No open files + checkNumberOfInferredProjects(projectService, 1); + const inferredProject5 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject4, [file4.path]); + assert.strictEqual(inferredProject5, inferredProject4); + + const file5: FileOrFolder = { + path: "/file5.ts", + content: "let zz = 1;" + }; + host.reloadFS(files.concat(configFile, file5)); + projectService.openClientFile(file5.path); + verifyScriptInfosAreUndefined([file1, file2, file3]); + assert.strictEqual(projectService.getScriptInfoForPath(file4.path as Path), find(infos, info => info.path === file4.path)); + assert.isDefined(projectService.getScriptInfoForPath(file5.path as Path)); + checkOpenFiles(projectService, [file4, file5]); + checkNumberOfConfiguredProjects(projectService, 0); + function verifyScriptInfos() { infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); } - function verifyConfiguredProjectStateAfterUpdate(_openRefCount: number) { + function verifyScriptInfosAreUndefined(files: FileOrFolder[]) { + for (const file of files) { + assert.isUndefined(projectService.getScriptInfoForPath(file.path as Path)); + } + } + + function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean) { checkNumberOfConfiguredProjects(projectService, 1); const configProject2 = projectService.configuredProjects.get(configFile.path); - assert.strictEqual(configProject1, configProject2); + assert.strictEqual(configProject2, configProject1); checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); - //assert.equal(configProject2.openRefCount, openRefCount); + assert.equal(configProject2.hasOpenRef(), hasOpenRef); } }); + it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => { + const file1: FileOrFolder = { + path: "/a/b/src/file1.ts", + content: "let x = 1;" + }; + const file2: FileOrFolder = { + path: "/a/b/src/file2.ts", + content: "let y = 1;" + }; + const file3: FileOrFolder = { + path: "/a/b/file3.ts", + content: "let z = 1;" + }; + const file4: FileOrFolder = { + path: "/a/file4.ts", + content: "let z = 1;" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ files: ["src/file1.ts", "file3.ts"] }) + }; + + const files = [file1, file2, file3]; + const hostFiles = files.concat(file4, configFile); + const host = createServerHost(hostFiles); + const projectService = createProjectService(host); + + projectService.openClientFile(file1.path); + projectService.openClientFile(file2.path); + projectService.openClientFile(file3.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + const configuredProject = projectService.configuredProjects.get(configFile.path); + assert.isTrue(configuredProject.hasOpenRef()); // file1 and file3 + checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]); + const inferredProject1 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject1, [file2.path]); + + projectService.closeClientFile(file1.path); + projectService.closeClientFile(file3.path); + assert.isFalse(configuredProject.hasOpenRef()); // No files + + configFile.content = "{}"; + host.reloadFS(files.concat(configFile)); + // Time out is not yet run so there is project update pending + assert.isTrue(configuredProject.hasOpenRef()); // Pending update and file2 might get into the project + + projectService.openClientFile(file4.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); + assert.isTrue(configuredProject.hasOpenRef()); // Pending update and F2 might get into the project + assert.strictEqual(projectService.inferredProjects[0], inferredProject1); + const inferredProject2 = projectService.inferredProjects[1]; + checkProjectActualFiles(inferredProject2, [file4.path]); + + host.runQueuedTimeoutCallbacks(); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); + assert.isTrue(configuredProject.hasOpenRef()); // file2 + checkProjectActualFiles(configuredProject, [file1.path, file2.path, file3.path, configFile.path]); + assert.strictEqual(projectService.inferredProjects[0], inferredProject2); + checkProjectActualFiles(inferredProject2, [file4.path]); + }); + it("language service disabled state is updated in external projects", () => { const f1 = { path: "/a/app.js", @@ -2265,18 +2373,36 @@ namespace ts.projectSystem { projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path); + assert.isTrue(project.hasOpenRef()); // f1 + assert.isFalse(project.isClosed()); projectService.closeClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); for (const f of [f1, f2, f3]) { - // There shouldnt be any script info as we closed the file that resulted in creation of it + // All the script infos should be present and contain the project since it is still alive. const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path)); assert.equal(scriptInfo.containingProjects.length, 1, `expect 1 containing projects for '${f.path}'`); assert.equal(scriptInfo.containingProjects[0], project, `expect configured project to be the only containing project for '${f.path}'`); } + + const f4 = { + path: "/aa.js", + content: "var x = 1" + }; + host.reloadFS([f1, f2, f3, config, f4]); + projectService.openClientFile(f4.path); + projectService.checkNumberOfProjects({ inferredProjects: 1 }); + assert.isFalse(project.hasOpenRef()); // No files + assert.isTrue(project.isClosed()); + + for (const f of [f1, f2, f3]) { + // All the script infos should not be present since the project is closed and orphan script infos are collected + assert.isUndefined(projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path))); + } }); it("language service disabled events are triggered", () => { @@ -2910,17 +3036,19 @@ namespace ts.projectSystem { projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // f projectService.closeClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // f + assert.isFalse(project.isClosed()); }); }); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 70598313a7365..a017ac5e45e6d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -554,6 +554,11 @@ namespace ts.server { }); } + /*@internal*/ + hasPendingProjectUpdate(project: Project) { + return this.pendingProjectUpdates.has(project.getProjectName()); + } + private sendProjectsUpdatedInBackgroundEvent() { if (!this.eventHandler) { return; @@ -795,8 +800,14 @@ namespace ts.server { ); } + /** Gets the config file existence info for the configured project */ + /*@internal*/ + getConfigFileExistenceInfo(project: ConfiguredProject) { + return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + } + private onConfigChangedForConfiguredProject(project: ConfiguredProject, eventKind: FileWatcherEventKind) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); if (eventKind === FileWatcherEventKind.Deleted) { // Update the cached status // We arent updating or removing the cached config file presence info as that will be taken care of by @@ -898,18 +909,6 @@ namespace ts.server { return project; } - private addToListOfOpenFiles(info: ScriptInfo) { - Debug.assert(!info.isOrphan()); - for (const p of info.containingProjects) { - // file is the part of configured project, addref the project - if (p.projectKind === ProjectKind.Configured) { - ((p)).addOpenRef(); - } - } - - this.openFiles.push(info); - } - /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured @@ -932,10 +931,8 @@ namespace ts.server { if (info.hasMixedContent) { info.registerFileUpdate(); } - // Delete the reference to the open configured projects but - // do not remove the project so that we can reuse this project + // Do not remove the project so that we can reuse this project // if it would need to be re-created with next file open - (p).deleteOpenRef(); } else if (p.projectKind === ProjectKind.Inferred && p.isRoot(info)) { // If this was the open root file of inferred project @@ -1025,7 +1022,7 @@ namespace ts.server { } private setConfigFileExistenceByNewConfiguredProject(project: ConfiguredProject) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); if (configFileExistenceInfo) { Debug.assert(configFileExistenceInfo.exists); // close existing watcher @@ -1054,7 +1051,7 @@ namespace ts.server { } private setConfigFileExistenceInfoByClosedConfiguredProject(closedProject: ConfiguredProject) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(closedProject.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(closedProject); Debug.assert(!!configFileExistenceInfo); if (configFileExistenceInfo.openFilesImpactedByConfigFile.size) { const configFileName = closedProject.getConfigFilePath(); @@ -1943,7 +1940,8 @@ namespace ts.server { this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); } - this.addToListOfOpenFiles(info); + Debug.assert(!info.isOrphan()); + this.openFiles.push(info); if (sendConfigFileDiagEvent) { configFileErrors = project.getAllProjectErrors(); @@ -2043,11 +2041,14 @@ namespace ts.server { } } - private closeConfiguredProject(configFile: NormalizedPath): boolean { + private closeConfiguredProjectReferencedFromExternalProject(configFile: NormalizedPath): boolean { const configuredProject = this.findConfiguredProjectByProjectName(configFile); - if (configuredProject && configuredProject.deleteOpenRef() === 0) { - this.removeProject(configuredProject); - return true; + if (configuredProject) { + configuredProject.deleteExternalProjectReference(); + if (!configuredProject.hasOpenRef()) { + this.removeProject(configuredProject); + return true; + } } return false; } @@ -2058,7 +2059,7 @@ namespace ts.server { if (configFiles) { let shouldRefreshInferredProjects = false; for (const configFile of configFiles) { - if (this.closeConfiguredProject(configFile)) { + if (this.closeConfiguredProjectReferencedFromExternalProject(configFile)) { shouldRefreshInferredProjects = true; } } @@ -2253,7 +2254,7 @@ namespace ts.server { const newConfig = tsConfigFiles[iNew]; const oldConfig = oldConfigFiles[iOld]; if (oldConfig < newConfig) { - this.closeConfiguredProject(oldConfig); + this.closeConfiguredProjectReferencedFromExternalProject(oldConfig); iOld++; } else if (oldConfig > newConfig) { @@ -2268,7 +2269,7 @@ namespace ts.server { } for (let i = iOld; i < oldConfigFiles.length; i++) { // projects for all remaining old config files should be closed - this.closeConfiguredProject(oldConfigFiles[i]); + this.closeConfiguredProjectReferencedFromExternalProject(oldConfigFiles[i]); } } } @@ -2283,7 +2284,7 @@ namespace ts.server { } if (project && !contains(exisingConfigFiles, tsconfigFile)) { // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project - project.addOpenRef(); + project.addExternalProjectReference(); } } } diff --git a/src/server/project.ts b/src/server/project.ts index 7653fbf93cfa4..395da1bd6436d 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -892,9 +892,7 @@ namespace ts.server { } getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( - fileName, /*scriptKind*/ undefined, /*hasMixedContent*/ undefined, this.directoryStructureHost - ); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(fileName); if (scriptInfo && !scriptInfo.isAttached(this)) { return Errors.ThrowProjectDoesNotContainDocument(fileName, this); } @@ -902,7 +900,7 @@ namespace ts.server { } getScriptInfo(uncheckedFileName: string) { - return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); + return this.projectService.getScriptInfo(uncheckedFileName); } filesToString(writeProjectFileNames: boolean) { @@ -1130,8 +1128,8 @@ namespace ts.server { private plugins: PluginModule[] = []; - /** Used for configured projects which may have multiple open roots */ - openRefCount = 0; + /** Ref count to the project when opened from external project */ + private externalProjectRefCount = 0; private projectErrors: Diagnostic[]; @@ -1342,17 +1340,43 @@ namespace ts.server { super.close(); } - addOpenRef() { - this.openRefCount++; + /* @internal */ + addExternalProjectReference() { + this.externalProjectRefCount++; } - deleteOpenRef() { - this.openRefCount--; - return this.openRefCount; + /* @internal */ + deleteExternalProjectReference() { + this.externalProjectRefCount--; } + /** Returns true if the project is needed by any of the open script info/external project */ + /* @internal */ hasOpenRef() { - return !!this.openRefCount; + if (!!this.externalProjectRefCount) { + return true; + } + + // Closed project doesnt have any reference + if (this.isClosed()) { + return false; + } + + const configFileExistenceInfo = this.projectService.getConfigFileExistenceInfo(this); + if (this.projectService.hasPendingProjectUpdate(this)) { + // If there is pending update for this project, + // we dont know if this project would be needed by any of the open files impacted by this config file + // In that case keep the project alive if there are open files impacted by this project + return !!configFileExistenceInfo.openFilesImpactedByConfigFile.size; + } + + // If there is no pending update for this project, + // We know exact set of open files that get impacted by this configured project as the files in the project + // The project is referenced only if open files impacted by this project are present in this project + return forEachEntry( + configFileExistenceInfo.openFilesImpactedByConfigFile, + (_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path)) + ) || false; } getEffectiveTypeRoots() { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 151c948602de4..204c718fabdb0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7211,8 +7211,8 @@ declare namespace ts.server { private directoriesWatchedForWildcards; readonly canonicalConfigFilePath: NormalizedPath; private plugins; - /** Used for configured projects which may have multiple open roots */ - openRefCount: number; + /** Ref count to the project when opened from external project */ + private externalProjectRefCount; private projectErrors; /** * If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph @@ -7236,9 +7236,6 @@ declare namespace ts.server { getTypeAcquisition(): TypeAcquisition; getExternalFiles(): SortedReadonlyArray; close(): void; - addOpenRef(): void; - deleteOpenRef(): number; - hasOpenRef(): boolean; getEffectiveTypeRoots(): string[]; } /** @@ -7468,7 +7465,6 @@ declare namespace ts.server { */ private onConfigFileChangeForOpenScriptInfo(configFileName, eventKind); private removeProject(project); - private addToListOfOpenFiles(info); /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured @@ -7576,7 +7572,7 @@ declare namespace ts.server { */ closeClientFile(uncheckedFileName: string): void; private collectChanges(lastKnownProjectVersions, currentProjects, result); - private closeConfiguredProject(configFile); + private closeConfiguredProjectReferencedFromExternalProject(configFile); closeExternalProject(uncheckedFileName: string, suppressRefresh?: boolean): void; openExternalProjects(projects: protocol.ExternalProject[]): void; /** Makes a filename safe to insert in a RegExp */ From 9af21eb00eb957240159745c181077e21df9da17 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 12 Oct 2017 12:53:12 -0700 Subject: [PATCH 155/246] Transform nested dynamic imports (#18998) * Fix nested dynamic imports when targeting es6 * Fixup nested dynamic imports when targeting downlevel * Remove duplicated expressions in UMD emit * Code review feedback, clone arg if need be * More CR feedback, apply user quotemark styles * Remove blank lines * Use behavior of visitEachChild instead of enw codepath, add new test, use createLiteral to retain quotemarks * Set lib flag for test --- src/compiler/transformers/generators.ts | 3 +- src/compiler/transformers/module/module.ts | 46 ++++++---- src/compiler/transformers/module/system.ts | 2 +- src/compiler/transformers/utilities.ts | 13 +++ .../reference/asyncImportNestedYield.js | 58 +++++++++++++ .../reference/asyncImportNestedYield.symbols | 6 ++ .../reference/asyncImportNestedYield.types | 14 ++++ .../dynamicImportWithNestedThis_es2015.js | 3 +- .../dynamicImportWithNestedThis_es5.js | 3 +- .../importCallExpressionGrammarError.js | 2 +- .../importCallExpressionNestedAMD.js | 33 ++++++++ .../importCallExpressionNestedAMD.symbols | 12 +++ .../importCallExpressionNestedAMD.types | 17 ++++ .../importCallExpressionNestedAMD2.js | 66 +++++++++++++++ .../importCallExpressionNestedAMD2.symbols | 12 +++ .../importCallExpressionNestedAMD2.types | 17 ++++ .../importCallExpressionNestedCJS.js | 28 +++++++ .../importCallExpressionNestedCJS.symbols | 12 +++ .../importCallExpressionNestedCJS.types | 17 ++++ .../importCallExpressionNestedCJS2.js | 61 ++++++++++++++ .../importCallExpressionNestedCJS2.symbols | 12 +++ .../importCallExpressionNestedCJS2.types | 17 ++++ ...mportCallExpressionNestedES2015.errors.txt | 15 ++++ .../importCallExpressionNestedES2015.js | 26 ++++++ .../importCallExpressionNestedES2015.symbols | 12 +++ .../importCallExpressionNestedES2015.types | 17 ++++ ...portCallExpressionNestedES20152.errors.txt | 15 ++++ .../importCallExpressionNestedES20152.js | 59 +++++++++++++ .../importCallExpressionNestedES20152.symbols | 12 +++ .../importCallExpressionNestedES20152.types | 17 ++++ .../importCallExpressionNestedESNext.js | 26 ++++++ .../importCallExpressionNestedESNext.symbols | 12 +++ .../importCallExpressionNestedESNext.types | 17 ++++ .../importCallExpressionNestedESNext2.js | 59 +++++++++++++ .../importCallExpressionNestedESNext2.symbols | 12 +++ .../importCallExpressionNestedESNext2.types | 17 ++++ .../importCallExpressionNestedSystem.js | 43 ++++++++++ .../importCallExpressionNestedSystem.symbols | 12 +++ .../importCallExpressionNestedSystem.types | 17 ++++ .../importCallExpressionNestedSystem2.js | 76 +++++++++++++++++ .../importCallExpressionNestedSystem2.symbols | 12 +++ .../importCallExpressionNestedSystem2.types | 17 ++++ .../importCallExpressionNestedUMD.js | 51 +++++++++++ .../importCallExpressionNestedUMD.symbols | 12 +++ .../importCallExpressionNestedUMD.types | 17 ++++ .../importCallExpressionNestedUMD2.js | 84 +++++++++++++++++++ .../importCallExpressionNestedUMD2.symbols | 12 +++ .../importCallExpressionNestedUMD2.types | 17 ++++ .../cases/compiler/asyncImportNestedYield.ts | 4 + .../importCallExpressionNestedAMD.ts | 11 +++ .../importCallExpressionNestedAMD2.ts | 11 +++ .../importCallExpressionNestedCJS.ts | 11 +++ .../importCallExpressionNestedCJS2.ts | 11 +++ .../importCallExpressionNestedES2015.ts | 11 +++ .../importCallExpressionNestedES20152.ts | 11 +++ .../importCallExpressionNestedESNext.ts | 11 +++ .../importCallExpressionNestedESNext2.ts | 11 +++ .../importCallExpressionNestedSystem.ts | 11 +++ .../importCallExpressionNestedSystem2.ts | 11 +++ .../importCallExpressionNestedUMD.ts | 11 +++ .../importCallExpressionNestedUMD2.ts | 11 +++ 61 files changed, 1254 insertions(+), 22 deletions(-) create mode 100644 tests/baselines/reference/asyncImportNestedYield.js create mode 100644 tests/baselines/reference/asyncImportNestedYield.symbols create mode 100644 tests/baselines/reference/asyncImportNestedYield.types create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD.js create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD.types create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD2.js create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD2.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedAMD2.types create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS.js create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS.types create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS2.js create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS2.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedCJS2.types create mode 100644 tests/baselines/reference/importCallExpressionNestedES2015.errors.txt create mode 100644 tests/baselines/reference/importCallExpressionNestedES2015.js create mode 100644 tests/baselines/reference/importCallExpressionNestedES2015.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedES2015.types create mode 100644 tests/baselines/reference/importCallExpressionNestedES20152.errors.txt create mode 100644 tests/baselines/reference/importCallExpressionNestedES20152.js create mode 100644 tests/baselines/reference/importCallExpressionNestedES20152.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedES20152.types create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext.js create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext.types create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext2.js create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext2.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedESNext2.types create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem.js create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem.types create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem2.js create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem2.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedSystem2.types create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD.js create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD.types create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD2.js create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD2.symbols create mode 100644 tests/baselines/reference/importCallExpressionNestedUMD2.types create mode 100644 tests/cases/compiler/asyncImportNestedYield.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD2.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS2.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedES2015.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedES20152.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext2.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem2.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD.ts create mode 100644 tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD2.ts diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 84ed997a70edd..7ede62b154055 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1112,7 +1112,7 @@ namespace ts { } function visitCallExpression(node: CallExpression) { - if (forEach(node.arguments, containsYield)) { + if (!isImportCall(node) && forEach(node.arguments, containsYield)) { // [source] // a.b(1, yield, 2); // @@ -1123,7 +1123,6 @@ namespace ts { // .yield resumeLabel // .mark resumeLabel // _b.apply(_a, _c.concat([%sent%, 2])); - const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true); return setOriginalNode( createFunctionApply( diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index ba262bf2c59d0..bd360fdffe404 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -21,7 +21,8 @@ namespace ts { const { startLexicalEnvironment, - endLexicalEnvironment + endLexicalEnvironment, + hoistVariableDeclaration } = context; const compilerOptions = context.getCompilerOptions(); @@ -519,18 +520,20 @@ namespace ts { } function visitImportCallExpression(node: ImportCall): Expression { + const argument = visitNode(firstOrUndefined(node.arguments), importCallExpressionVisitor); + const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis); switch (compilerOptions.module) { case ModuleKind.AMD: - return transformImportCallExpressionAMD(node); + return createImportCallExpressionAMD(argument, containsLexicalThis); case ModuleKind.UMD: - return transformImportCallExpressionUMD(node); + return createImportCallExpressionUMD(argument, containsLexicalThis); case ModuleKind.CommonJS: default: - return transformImportCallExpressionCommonJS(node); + return createImportCallExpressionCommonJS(argument, containsLexicalThis); } } - function transformImportCallExpressionUMD(node: ImportCall): Expression { + function createImportCallExpressionUMD(arg: Expression | undefined, containsLexicalThis: boolean): Expression { // (function (factory) { // ... (regular UMD) // } @@ -545,14 +548,25 @@ namespace ts { // : new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ // }); needUMDDynamicImportHelper = true; - return createConditional( - /*condition*/ createIdentifier("__syncRequire"), - /*whenTrue*/ transformImportCallExpressionCommonJS(node), - /*whenFalse*/ transformImportCallExpressionAMD(node) - ); + if (isSimpleCopiableExpression(arg)) { + const argClone = isGeneratedIdentifier(arg) ? arg : isStringLiteral(arg) ? createLiteral(arg) : setEmitFlags(setTextRange(getSynthesizedClone(arg), arg), EmitFlags.NoComments); + return createConditional( + /*condition*/ createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(arg, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(argClone, containsLexicalThis) + ); + } + else { + const temp = createTempVariable(hoistVariableDeclaration); + return createComma(createAssignment(temp, arg), createConditional( + /*condition*/ createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(temp, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(temp, containsLexicalThis) + )); + } } - function transformImportCallExpressionAMD(node: ImportCall): Expression { + function createImportCallExpressionAMD(arg: Expression | undefined, containsLexicalThis: boolean): Expression { // improt("./blah") // emit as // define(["require", "exports", "blah"], function (require, exports) { @@ -570,7 +584,7 @@ namespace ts { createCall( createIdentifier("require"), /*typeArguments*/ undefined, - [createArrayLiteral([firstOrUndefined(node.arguments) || createOmittedExpression()]), resolve, reject] + [createArrayLiteral([arg || createOmittedExpression()]), resolve, reject] ) ) ]); @@ -598,7 +612,7 @@ namespace ts { // if there is a lexical 'this' in the import call arguments, ensure we indicate // that this new function expression indicates it captures 'this' so that the // es2015 transformer will properly substitute 'this' with '_this'. - if (node.transformFlags & TransformFlags.ContainsLexicalThis) { + if (containsLexicalThis) { setEmitFlags(func, EmitFlags.CapturesThis); } } @@ -606,14 +620,14 @@ namespace ts { return createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); } - function transformImportCallExpressionCommonJS(node: ImportCall): Expression { + function createImportCallExpressionCommonJS(arg: Expression | undefined, containsLexicalThis: boolean): Expression { // import("./blah") // emit as // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ // We have to wrap require in then callback so that require is done in asynchronously // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately const promiseResolveCall = createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); - const requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, node.arguments); + const requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []); let func: FunctionExpression | ArrowFunction; if (languageVersion >= ScriptTarget.ES2015) { @@ -638,7 +652,7 @@ namespace ts { // if there is a lexical 'this' in the import call arguments, ensure we indicate // that this new function expression indicates it captures 'this' so that the // es2015 transformer will properly substitute 'this' with '_this'. - if (node.transformFlags & TransformFlags.ContainsLexicalThis) { + if (containsLexicalThis) { setEmitFlags(func, EmitFlags.CapturesThis); } } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index af77c499e8d3d..ed943eb90ce79 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1495,7 +1495,7 @@ namespace ts { createIdentifier("import") ), /*typeArguments*/ undefined, - node.arguments + some(node.arguments) ? [visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : [] ); } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 00a0753eaa156..a012c9be7db9a 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -178,4 +178,17 @@ namespace ts { } return values; } + + /** + * Used in the module transformer to check if an expression is reasonably without sideeffect, + * and thus better to copy into multiple places rather than to cache in a temporary variable + * - this is mostly subjective beyond the requirement that the expression not be sideeffecting + */ + export function isSimpleCopiableExpression(expression: Expression) { + return expression.kind === SyntaxKind.StringLiteral || + expression.kind === SyntaxKind.NumericLiteral || + expression.kind === SyntaxKind.NoSubstitutionTemplateLiteral || + isKeyword(expression.kind) || + isIdentifier(expression); + } } \ No newline at end of file diff --git a/tests/baselines/reference/asyncImportNestedYield.js b/tests/baselines/reference/asyncImportNestedYield.js new file mode 100644 index 0000000000000..0dd76a13ace8c --- /dev/null +++ b/tests/baselines/reference/asyncImportNestedYield.js @@ -0,0 +1,58 @@ +//// [asyncImportNestedYield.ts] +async function* foo() { + import((await import(yield "foo")).default); +} + +//// [asyncImportNestedYield.js] +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +function foo() { + return __asyncGenerator(this, arguments, function foo_1() { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, "foo"]; + case 1: return [4 /*yield*/, __await.apply(void 0, [Promise.resolve().then(function () { return require(_a.sent()); })])]; + case 2: + Promise.resolve().then(function () { return require((_a.sent())["default"]); }); + return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/asyncImportNestedYield.symbols b/tests/baselines/reference/asyncImportNestedYield.symbols new file mode 100644 index 0000000000000..01107ba5bf6bf --- /dev/null +++ b/tests/baselines/reference/asyncImportNestedYield.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/asyncImportNestedYield.ts === +async function* foo() { +>foo : Symbol(foo, Decl(asyncImportNestedYield.ts, 0, 0)) + + import((await import(yield "foo")).default); +} diff --git a/tests/baselines/reference/asyncImportNestedYield.types b/tests/baselines/reference/asyncImportNestedYield.types new file mode 100644 index 0000000000000..872e314150030 --- /dev/null +++ b/tests/baselines/reference/asyncImportNestedYield.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/asyncImportNestedYield.ts === +async function* foo() { +>foo : () => AsyncIterableIterator<"foo"> + + import((await import(yield "foo")).default); +>import((await import(yield "foo")).default) : Promise +>(await import(yield "foo")).default : any +>(await import(yield "foo")) : any +>await import(yield "foo") : any +>import(yield "foo") : Promise +>yield "foo" : any +>"foo" : "foo" +>default : any +} diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js index 86fba0c0b5d98..4f79e0caec1c2 100644 --- a/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es2015.js @@ -29,7 +29,8 @@ c.dynamic(); this._path = './other'; } dynamic() { - return __syncRequire ? Promise.resolve().then(() => require(this._path)) : new Promise((resolve_1, reject_1) => { require([this._path], resolve_1, reject_1); }); + return _a = this._path, __syncRequire ? Promise.resolve().then(() => require(_a)) : new Promise((resolve_1, reject_1) => { require([_a], resolve_1, reject_1); }); + var _a; } } const c = new C(); diff --git a/tests/baselines/reference/dynamicImportWithNestedThis_es5.js b/tests/baselines/reference/dynamicImportWithNestedThis_es5.js index cde1979b25b54..fcfde9e9887f1 100644 --- a/tests/baselines/reference/dynamicImportWithNestedThis_es5.js +++ b/tests/baselines/reference/dynamicImportWithNestedThis_es5.js @@ -30,7 +30,8 @@ c.dynamic(); } C.prototype.dynamic = function () { var _this = this; - return __syncRequire ? Promise.resolve().then(function () { return require(_this._path); }) : new Promise(function (resolve_1, reject_1) { require([_this._path], resolve_1, reject_1); }); + return _a = this._path, __syncRequire ? Promise.resolve().then(function () { return require(_a); }) : new Promise(function (resolve_1, reject_1) { require([_a], resolve_1, reject_1); }); + var _a; }; return C; }()); diff --git a/tests/baselines/reference/importCallExpressionGrammarError.js b/tests/baselines/reference/importCallExpressionGrammarError.js index e2ffc55577d3b..435eab35d4ea5 100644 --- a/tests/baselines/reference/importCallExpressionGrammarError.js +++ b/tests/baselines/reference/importCallExpressionGrammarError.js @@ -16,4 +16,4 @@ Promise.resolve().then(() => require(...["PathModule"])); var p1 = Promise.resolve().then(() => require(...a)); const p2 = Promise.resolve().then(() => require()); const p3 = Promise.resolve().then(() => require()); -const p4 = Promise.resolve().then(() => require("pathToModule", "secondModule")); +const p4 = Promise.resolve().then(() => require("pathToModule")); diff --git a/tests/baselines/reference/importCallExpressionNestedAMD.js b/tests/baselines/reference/importCallExpressionNestedAMD.js new file mode 100644 index 0000000000000..dc211d4400378 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD.js @@ -0,0 +1,33 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = "./foo"; +}); +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +define(["require", "exports"], function (require, exports) { + "use strict"; + function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield new Promise((resolve_1, reject_1) => { require([(yield new Promise((resolve_2, reject_2) => { require(["./foo"], resolve_2, reject_2); })).default], resolve_1, reject_1); }); + }); + } +}); diff --git a/tests/baselines/reference/importCallExpressionNestedAMD.symbols b/tests/baselines/reference/importCallExpressionNestedAMD.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedAMD.types b/tests/baselines/reference/importCallExpressionNestedAMD.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedAMD2.js b/tests/baselines/reference/importCallExpressionNestedAMD2.js new file mode 100644 index 0000000000000..1e159af2180a6 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD2.js @@ -0,0 +1,66 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD2.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = "./foo"; +}); +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +define(["require", "exports"], function (require, exports) { + "use strict"; + function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, new Promise(function (resolve_1, reject_1) { require(["./foo"], resolve_1, reject_1); })]; + case 1: return [4 /*yield*/, new Promise(function (resolve_2, reject_2) { require([(_a.sent()).default], resolve_2, reject_2); })]; + case 2: return [2 /*return*/, _a.sent()]; + } + }); + }); + } +}); diff --git a/tests/baselines/reference/importCallExpressionNestedAMD2.symbols b/tests/baselines/reference/importCallExpressionNestedAMD2.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedAMD2.types b/tests/baselines/reference/importCallExpressionNestedAMD2.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedAMD2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS.js b/tests/baselines/reference/importCallExpressionNestedCJS.js new file mode 100644 index 0000000000000..07c0f234bf7dc --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS.js @@ -0,0 +1,28 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield Promise.resolve().then(() => require((yield Promise.resolve().then(() => require("./foo"))).default)); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS.symbols b/tests/baselines/reference/importCallExpressionNestedCJS.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS.types b/tests/baselines/reference/importCallExpressionNestedCJS.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS2.js b/tests/baselines/reference/importCallExpressionNestedCJS2.js new file mode 100644 index 0000000000000..c76044ec05c2e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS2.js @@ -0,0 +1,61 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS2.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, Promise.resolve().then(function () { return require("./foo"); })]; + case 1: return [4 /*yield*/, Promise.resolve().then(function () { return require((_a.sent()).default); })]; + case 2: return [2 /*return*/, _a.sent()]; + } + }); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS2.symbols b/tests/baselines/reference/importCallExpressionNestedCJS2.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedCJS2.types b/tests/baselines/reference/importCallExpressionNestedCJS2.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedCJS2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt new file mode 100644 index 0000000000000..1208dd0c70907 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES2015.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + + +==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== + export default "./foo"; + +==== tests/cases/conformance/dynamicImport/index.ts (2 errors) ==== + async function foo() { + return await import((await import("./foo")).default); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + ~~~~~~~~~~~~~~~ +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.js b/tests/baselines/reference/importCallExpressionNestedES2015.js new file mode 100644 index 0000000000000..5c8a6a9edb560 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES2015.js @@ -0,0 +1,26 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedES2015.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +export default "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield import((yield import("./foo")).default); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.symbols b/tests/baselines/reference/importCallExpressionNestedES2015.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES2015.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedES2015.types b/tests/baselines/reference/importCallExpressionNestedES2015.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES2015.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt new file mode 100644 index 0000000000000..1208dd0c70907 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES20152.errors.txt @@ -0,0 +1,15 @@ +tests/cases/conformance/dynamicImport/index.ts(2,18): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. +tests/cases/conformance/dynamicImport/index.ts(2,32): error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + + +==== tests/cases/conformance/dynamicImport/foo.ts (0 errors) ==== + export default "./foo"; + +==== tests/cases/conformance/dynamicImport/index.ts (2 errors) ==== + async function foo() { + return await import((await import("./foo")).default); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + ~~~~~~~~~~~~~~~ +!!! error TS1323: Dynamic import cannot be used when targeting ECMAScript 2015 modules. + } \ No newline at end of file diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.js b/tests/baselines/reference/importCallExpressionNestedES20152.js new file mode 100644 index 0000000000000..2496f43f84fec --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES20152.js @@ -0,0 +1,59 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedES20152.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +export default "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, import("./foo")]; + case 1: return [4 /*yield*/, import((_a.sent()).default)]; + case 2: return [2 /*return*/, _a.sent()]; + } + }); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.symbols b/tests/baselines/reference/importCallExpressionNestedES20152.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES20152.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedES20152.types b/tests/baselines/reference/importCallExpressionNestedES20152.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedES20152.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext.js b/tests/baselines/reference/importCallExpressionNestedESNext.js new file mode 100644 index 0000000000000..8ec9b988201dc --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext.js @@ -0,0 +1,26 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +export default "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield import((yield import("./foo")).default); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext.symbols b/tests/baselines/reference/importCallExpressionNestedESNext.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext.types b/tests/baselines/reference/importCallExpressionNestedESNext.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext2.js b/tests/baselines/reference/importCallExpressionNestedESNext2.js new file mode 100644 index 0000000000000..9a4d9f44f7a94 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext2.js @@ -0,0 +1,59 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext2.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +export default "./foo"; +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, import("./foo")]; + case 1: return [4 /*yield*/, import((_a.sent()).default)]; + case 2: return [2 /*return*/, _a.sent()]; + } + }); + }); +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext2.symbols b/tests/baselines/reference/importCallExpressionNestedESNext2.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedESNext2.types b/tests/baselines/reference/importCallExpressionNestedESNext2.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedESNext2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedSystem.js b/tests/baselines/reference/importCallExpressionNestedSystem.js new file mode 100644 index 0000000000000..839a3601e3898 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem.js @@ -0,0 +1,43 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("default", "./foo"); + } + }; +}); +//// [index.js] +System.register([], function (exports_1, context_1) { + var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __moduleName = context_1 && context_1.id; + function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield context_1.import((yield context_1.import("./foo")).default); + }); + } + return { + setters: [], + execute: function () { + } + }; +}); diff --git a/tests/baselines/reference/importCallExpressionNestedSystem.symbols b/tests/baselines/reference/importCallExpressionNestedSystem.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedSystem.types b/tests/baselines/reference/importCallExpressionNestedSystem.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedSystem2.js b/tests/baselines/reference/importCallExpressionNestedSystem2.js new file mode 100644 index 0000000000000..9b0fc20886d56 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem2.js @@ -0,0 +1,76 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem2.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + exports_1("default", "./foo"); + } + }; +}); +//// [index.js] +System.register([], function (exports_1, context_1) { + var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + var __moduleName = context_1 && context_1.id; + function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, context_1.import("./foo")]; + case 1: return [4 /*yield*/, context_1.import((_a.sent()).default)]; + case 2: return [2 /*return*/, _a.sent()]; + } + }); + }); + } + return { + setters: [], + execute: function () { + } + }; +}); diff --git a/tests/baselines/reference/importCallExpressionNestedSystem2.symbols b/tests/baselines/reference/importCallExpressionNestedSystem2.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedSystem2.types b/tests/baselines/reference/importCallExpressionNestedSystem2.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedSystem2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedUMD.js b/tests/baselines/reference/importCallExpressionNestedUMD.js new file mode 100644 index 0000000000000..0b1d20af8a421 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD.js @@ -0,0 +1,51 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = "./foo"; +}); +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + function foo() { + return __awaiter(this, void 0, void 0, function* () { + return yield _a = (yield __syncRequire ? Promise.resolve().then(() => require("./foo")) : new Promise((resolve_1, reject_1) => { require(["./foo"], resolve_1, reject_1); })).default, __syncRequire ? Promise.resolve().then(() => require(_a)) : new Promise((resolve_2, reject_2) => { require([_a], resolve_2, reject_2); }); + var _a; + }); + } +}); diff --git a/tests/baselines/reference/importCallExpressionNestedUMD.symbols b/tests/baselines/reference/importCallExpressionNestedUMD.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedUMD.types b/tests/baselines/reference/importCallExpressionNestedUMD.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/baselines/reference/importCallExpressionNestedUMD2.js b/tests/baselines/reference/importCallExpressionNestedUMD2.js new file mode 100644 index 0000000000000..86fd0bfa8f1f8 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD2.js @@ -0,0 +1,84 @@ +//// [tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD2.ts] //// + +//// [foo.ts] +export default "./foo"; + +//// [index.ts] +async function foo() { + return await import((await import("./foo")).default); +} + +//// [foo.js] +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.default = "./foo"; +}); +//// [index.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +(function (factory) { + if (typeof module === "object" && typeof module.exports === "object") { + var v = factory(require, exports); + if (v !== undefined) module.exports = v; + } + else if (typeof define === "function" && define.amd) { + define(["require", "exports"], factory); + } +})(function (require, exports) { + "use strict"; + var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + function foo() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, __syncRequire ? Promise.resolve().then(function () { return require("./foo"); }) : new Promise(function (resolve_1, reject_1) { require(["./foo"], resolve_1, reject_1); })]; + case 1: return [4 /*yield*/, (_b = (_a.sent()).default, __syncRequire ? Promise.resolve().then(function () { return require(_b); }) : new Promise(function (resolve_2, reject_2) { require([_b], resolve_2, reject_2); }))]; + case 2: return [2 /*return*/, _a.sent()]; + } + var _b; + }); + }); + } +}); diff --git a/tests/baselines/reference/importCallExpressionNestedUMD2.symbols b/tests/baselines/reference/importCallExpressionNestedUMD2.symbols new file mode 100644 index 0000000000000..67e2eabd6fd5e --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD2.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : Symbol(foo, Decl(index.ts, 0, 0)) + + return await import((await import("./foo")).default); +>(await import("./foo")).default : Symbol(default, Decl(foo.ts, 0, 0)) +>"./foo" : Symbol("tests/cases/conformance/dynamicImport/foo", Decl(foo.ts, 0, 0)) +>default : Symbol(default, Decl(foo.ts, 0, 0)) +} diff --git a/tests/baselines/reference/importCallExpressionNestedUMD2.types b/tests/baselines/reference/importCallExpressionNestedUMD2.types new file mode 100644 index 0000000000000..2f74d78b6c845 --- /dev/null +++ b/tests/baselines/reference/importCallExpressionNestedUMD2.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/dynamicImport/foo.ts === +export default "./foo"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/dynamicImport/index.ts === +async function foo() { +>foo : () => Promise + + return await import((await import("./foo")).default); +>await import((await import("./foo")).default) : any +>import((await import("./foo")).default) : Promise +>(await import("./foo")).default : "./foo" +>(await import("./foo")) : typeof "tests/cases/conformance/dynamicImport/foo" +>await import("./foo") : typeof "tests/cases/conformance/dynamicImport/foo" +>import("./foo") : Promise +>"./foo" : "./foo" +>default : "./foo" +} diff --git a/tests/cases/compiler/asyncImportNestedYield.ts b/tests/cases/compiler/asyncImportNestedYield.ts new file mode 100644 index 0000000000000..78b022e07971d --- /dev/null +++ b/tests/cases/compiler/asyncImportNestedYield.ts @@ -0,0 +1,4 @@ +// @lib: esnext +async function* foo() { + import((await import(yield "foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD.ts new file mode 100644 index 0000000000000..1dbde4e19561d --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD.ts @@ -0,0 +1,11 @@ +// @module: amd +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD2.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD2.ts new file mode 100644 index 0000000000000..79540087a58f7 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedAMD2.ts @@ -0,0 +1,11 @@ +// @module: amd +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS.ts new file mode 100644 index 0000000000000..5c99e56ecdac1 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS.ts @@ -0,0 +1,11 @@ +// @module: commonjs +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS2.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS2.ts new file mode 100644 index 0000000000000..0776053d668ef --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedCJS2.ts @@ -0,0 +1,11 @@ +// @module: commonjs +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedES2015.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedES2015.ts new file mode 100644 index 0000000000000..9708f466f5e4d --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedES2015.ts @@ -0,0 +1,11 @@ +// @module: es2015 +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedES20152.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedES20152.ts new file mode 100644 index 0000000000000..c78b38db193a9 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedES20152.ts @@ -0,0 +1,11 @@ +// @module: es2015 +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext.ts new file mode 100644 index 0000000000000..fffc12a77260a --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext.ts @@ -0,0 +1,11 @@ +// @module: esnext +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext2.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext2.ts new file mode 100644 index 0000000000000..246e9d931f024 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedESNext2.ts @@ -0,0 +1,11 @@ +// @module: esnext +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem.ts new file mode 100644 index 0000000000000..04a11ac816991 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem.ts @@ -0,0 +1,11 @@ +// @module: system +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem2.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem2.ts new file mode 100644 index 0000000000000..f8b2d4513ee06 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedSystem2.ts @@ -0,0 +1,11 @@ +// @module: system +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD.ts new file mode 100644 index 0000000000000..8b900a7dbd674 --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD.ts @@ -0,0 +1,11 @@ +// @module: umd +// @target: es6 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file diff --git a/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD2.ts b/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD2.ts new file mode 100644 index 0000000000000..e07dba0d2e5ed --- /dev/null +++ b/tests/cases/conformance/dynamicImport/importCallExpressionNestedUMD2.ts @@ -0,0 +1,11 @@ +// @module: umd +// @target: es5 +// @skipLibCheck: true +// @lib: es6 +// @filename: foo.ts +export default "./foo"; + +// @filename: index.ts +async function foo() { + return await import((await import("./foo")).default); +} \ No newline at end of file From 6bfad5222522fbc614ba35b860f09c4736a535a4 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 12 Oct 2017 13:23:08 -0700 Subject: [PATCH 156/246] Update missed baseline --- src/harness/unittests/tsserverProjectSystem.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 716c36d1e5d2a..7dce256e38831 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -4412,9 +4412,9 @@ namespace ts.projectSystem { fileName: "/a.ts", textChanges: [ { - start: { line: 2, offset: 1 }, - end: { line: 3, offset: 1 }, - newText: " newFunction();\n", + start: { line: 2, offset: 3 }, + end: { line: 2, offset: 5 }, + newText: "newFunction();", }, { start: { line: 3, offset: 2 }, From 2ea4cfe23bf0648c099a79a8a1d976febb2e2610 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Thu, 12 Oct 2017 11:37:31 -0700 Subject: [PATCH 157/246] Insert a line break before a function at EOF if needed This is a pre-existing issue that became more obvious after refining trivia handling. --- src/harness/unittests/tsserverProjectSystem.ts | 2 +- src/services/refactors/extractSymbol.ts | 5 ++++- .../baselines/reference/extractFunction/extractFunction1.ts | 1 + .../baselines/reference/extractFunction/extractFunction10.ts | 1 + .../baselines/reference/extractFunction/extractFunction11.ts | 1 + .../baselines/reference/extractFunction/extractFunction13.ts | 1 + .../baselines/reference/extractFunction/extractFunction14.ts | 1 + .../baselines/reference/extractFunction/extractFunction15.ts | 1 + .../baselines/reference/extractFunction/extractFunction16.ts | 1 + .../baselines/reference/extractFunction/extractFunction17.ts | 1 + .../baselines/reference/extractFunction/extractFunction18.ts | 1 + .../baselines/reference/extractFunction/extractFunction19.ts | 1 + .../baselines/reference/extractFunction/extractFunction2.ts | 1 + .../baselines/reference/extractFunction/extractFunction20.js | 1 + .../baselines/reference/extractFunction/extractFunction20.ts | 1 + .../baselines/reference/extractFunction/extractFunction21.js | 1 + .../baselines/reference/extractFunction/extractFunction21.ts | 1 + .../baselines/reference/extractFunction/extractFunction22.js | 1 + .../baselines/reference/extractFunction/extractFunction22.ts | 1 + .../baselines/reference/extractFunction/extractFunction23.ts | 1 + .../baselines/reference/extractFunction/extractFunction24.js | 1 + .../baselines/reference/extractFunction/extractFunction24.ts | 1 + .../baselines/reference/extractFunction/extractFunction26.js | 1 + .../baselines/reference/extractFunction/extractFunction26.ts | 1 + .../baselines/reference/extractFunction/extractFunction27.js | 1 + .../baselines/reference/extractFunction/extractFunction27.ts | 1 + .../baselines/reference/extractFunction/extractFunction28.js | 1 + .../baselines/reference/extractFunction/extractFunction28.ts | 1 + .../baselines/reference/extractFunction/extractFunction3.ts | 1 + .../baselines/reference/extractFunction/extractFunction30.ts | 1 + .../baselines/reference/extractFunction/extractFunction31.ts | 1 + .../baselines/reference/extractFunction/extractFunction32.ts | 1 + .../baselines/reference/extractFunction/extractFunction33.js | 1 + .../baselines/reference/extractFunction/extractFunction33.ts | 1 + .../baselines/reference/extractFunction/extractFunction4.ts | 1 + .../baselines/reference/extractFunction/extractFunction5.ts | 1 + .../baselines/reference/extractFunction/extractFunction6.ts | 1 + .../baselines/reference/extractFunction/extractFunction7.ts | 1 + .../baselines/reference/extractFunction/extractFunction9.ts | 1 + .../extractFunction/extractFunction_PreserveTrivia.js | 1 + .../extractFunction/extractFunction_PreserveTrivia.ts | 1 + .../extractFunction/extractFunction_RepeatedSubstitution.ts | 1 + .../extractFunction_VariableDeclaration_ShorthandProperty.js | 1 + .../extractFunction_VariableDeclaration_ShorthandProperty.ts | 1 + ...xtractFunction_VariableDeclaration_Writes_Const_NoType.js | 1 + ...xtractFunction_VariableDeclaration_Writes_Const_NoType.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Const_Type.ts | 1 + ...ctFunction_VariableDeclaration_Writes_Let_LiteralType1.ts | 1 + ...ctFunction_VariableDeclaration_Writes_Let_LiteralType2.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Let_NoType.js | 1 + .../extractFunction_VariableDeclaration_Writes_Let_NoType.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Let_Type.ts | 1 + ...nction_VariableDeclaration_Writes_Let_TypeWithComments.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Mixed1.js | 1 + .../extractFunction_VariableDeclaration_Writes_Mixed1.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Mixed2.js | 1 + .../extractFunction_VariableDeclaration_Writes_Mixed2.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Mixed3.ts | 1 + ...ractFunction_VariableDeclaration_Writes_UnionUndefined.ts | 1 + .../extractFunction_VariableDeclaration_Writes_Var.js | 1 + .../extractFunction_VariableDeclaration_Writes_Var.ts | 1 + tests/cases/fourslash/extract-method-empty-namespace.ts | 1 + tests/cases/fourslash/extract-method-formatting.ts | 1 + tests/cases/fourslash/extract-method-uniqueName.ts | 1 + tests/cases/fourslash/extract-method10.ts | 1 + tests/cases/fourslash/extract-method14.ts | 1 + tests/cases/fourslash/extract-method15.ts | 1 + tests/cases/fourslash/extract-method18.ts | 1 + tests/cases/fourslash/extract-method2.ts | 1 + tests/cases/fourslash/extract-method24.ts | 1 + tests/cases/fourslash/extract-method7.ts | 1 + 71 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 40be5e02eead1..4929cbfbaa517 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -4526,7 +4526,7 @@ namespace ts.projectSystem { { start: { line: 3, offset: 2 }, end: { line: 3, offset: 2 }, - newText: "\nfunction newFunction() {\n 1;\n}\n", + newText: "\n\nfunction newFunction() {\n 1;\n}\n", }, ] } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 715b42b6bc89a..ebe0cb4fa4415 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -785,7 +785,10 @@ namespace ts.refactor.extractSymbol { changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter }); } else { - changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter }); + changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { + prefix: isLineBreak(file.text.charCodeAt(scope.getLastToken().pos)) ? context.newLineCharacter : context.newLineCharacter + context.newLineCharacter, + suffix: context.newLineCharacter + }); } const newNodes: Node[] = []; diff --git a/tests/baselines/reference/extractFunction/extractFunction1.ts b/tests/baselines/reference/extractFunction/extractFunction1.ts index 8243644e1efd0..4b0b7dd9f2e16 100644 --- a/tests/baselines/reference/extractFunction/extractFunction1.ts +++ b/tests/baselines/reference/extractFunction/extractFunction1.ts @@ -89,6 +89,7 @@ namespace A { } } } + function newFunction(x: number, a: number, foo: () => void) { let y = 5; let z = x; diff --git a/tests/baselines/reference/extractFunction/extractFunction10.ts b/tests/baselines/reference/extractFunction/extractFunction10.ts index a15381c1a18ba..99651f03e88d1 100644 --- a/tests/baselines/reference/extractFunction/extractFunction10.ts +++ b/tests/baselines/reference/extractFunction/extractFunction10.ts @@ -49,6 +49,7 @@ namespace A { } } } + function newFunction() { let a1: A.I = { x: 1 }; return a1.x + 10; diff --git a/tests/baselines/reference/extractFunction/extractFunction11.ts b/tests/baselines/reference/extractFunction/extractFunction11.ts index 4bb88123a2f40..baca3914b039c 100644 --- a/tests/baselines/reference/extractFunction/extractFunction11.ts +++ b/tests/baselines/reference/extractFunction/extractFunction11.ts @@ -61,6 +61,7 @@ namespace A { } } } + function newFunction(y: number, z: number) { let a1 = { x: 1 }; y = 10; diff --git a/tests/baselines/reference/extractFunction/extractFunction13.ts b/tests/baselines/reference/extractFunction/extractFunction13.ts index 662701ebf415a..e39476160c567 100644 --- a/tests/baselines/reference/extractFunction/extractFunction13.ts +++ b/tests/baselines/reference/extractFunction/extractFunction13.ts @@ -66,6 +66,7 @@ } } } + function newFunction(t1a: T1a, t2a: T2a, u1a: U1a, u2a: U2a, u3a: U3a) { t1a.toString(); t2a.toString(); diff --git a/tests/baselines/reference/extractFunction/extractFunction14.ts b/tests/baselines/reference/extractFunction/extractFunction14.ts index 53cabbe600f91..86f8c9b5b6304 100644 --- a/tests/baselines/reference/extractFunction/extractFunction14.ts +++ b/tests/baselines/reference/extractFunction/extractFunction14.ts @@ -33,6 +33,7 @@ function F(t1: T) { /*RENAME*/newFunction(t1, t2); } } + function newFunction(t1: T, t2: T) { t1.toString(); t2.toString(); diff --git a/tests/baselines/reference/extractFunction/extractFunction15.ts b/tests/baselines/reference/extractFunction/extractFunction15.ts index a09383282aa19..3b291f4d86c70 100644 --- a/tests/baselines/reference/extractFunction/extractFunction15.ts +++ b/tests/baselines/reference/extractFunction/extractFunction15.ts @@ -30,6 +30,7 @@ function F(t1: T) { /*RENAME*/newFunction(t2); } } + function newFunction(t2: U) { t2.toString(); } diff --git a/tests/baselines/reference/extractFunction/extractFunction16.ts b/tests/baselines/reference/extractFunction/extractFunction16.ts index 79c72f31198b3..5800fa6945bef 100644 --- a/tests/baselines/reference/extractFunction/extractFunction16.ts +++ b/tests/baselines/reference/extractFunction/extractFunction16.ts @@ -14,6 +14,7 @@ function F() { function F() { const array: T[] = /*RENAME*/newFunction(); } + function newFunction(): T[] { return []; } diff --git a/tests/baselines/reference/extractFunction/extractFunction17.ts b/tests/baselines/reference/extractFunction/extractFunction17.ts index 733b1b27623d3..45d9953fb9504 100644 --- a/tests/baselines/reference/extractFunction/extractFunction17.ts +++ b/tests/baselines/reference/extractFunction/extractFunction17.ts @@ -20,6 +20,7 @@ class C { /*RENAME*/newFunction(t1); } } + function newFunction(t1: T1) { t1.toString(); } diff --git a/tests/baselines/reference/extractFunction/extractFunction18.ts b/tests/baselines/reference/extractFunction/extractFunction18.ts index 8c44de1298163..bdfcce6bbdc69 100644 --- a/tests/baselines/reference/extractFunction/extractFunction18.ts +++ b/tests/baselines/reference/extractFunction/extractFunction18.ts @@ -20,6 +20,7 @@ class C { /*RENAME*/newFunction(t1); } } + function newFunction(t1: T1) { t1.toString(); } diff --git a/tests/baselines/reference/extractFunction/extractFunction19.ts b/tests/baselines/reference/extractFunction/extractFunction19.ts index 3a2723513f463..0b3192a49fb8f 100644 --- a/tests/baselines/reference/extractFunction/extractFunction19.ts +++ b/tests/baselines/reference/extractFunction/extractFunction19.ts @@ -14,6 +14,7 @@ function F(v: V) { function F(v: V) { /*RENAME*/newFunction(v); } + function newFunction(v: V) { v.toString(); } diff --git a/tests/baselines/reference/extractFunction/extractFunction2.ts b/tests/baselines/reference/extractFunction/extractFunction2.ts index 3872812b31281..be72a7fd52f6a 100644 --- a/tests/baselines/reference/extractFunction/extractFunction2.ts +++ b/tests/baselines/reference/extractFunction/extractFunction2.ts @@ -78,6 +78,7 @@ namespace A { } } } + function newFunction(x: number, foo: () => void) { let y = 5; let z = x; diff --git a/tests/baselines/reference/extractFunction/extractFunction20.js b/tests/baselines/reference/extractFunction/extractFunction20.js index b65d3dae5da67..17bef1c604450 100644 --- a/tests/baselines/reference/extractFunction/extractFunction20.js +++ b/tests/baselines/reference/extractFunction/extractFunction20.js @@ -22,6 +22,7 @@ const _ = class { return /*RENAME*/newFunction(); } } + function newFunction() { let a1 = { x: 1 }; return a1.x + 10; diff --git a/tests/baselines/reference/extractFunction/extractFunction20.ts b/tests/baselines/reference/extractFunction/extractFunction20.ts index 1fe72020ad7da..ce09d4457d30a 100644 --- a/tests/baselines/reference/extractFunction/extractFunction20.ts +++ b/tests/baselines/reference/extractFunction/extractFunction20.ts @@ -22,6 +22,7 @@ const _ = class { return /*RENAME*/newFunction(); } } + function newFunction() { let a1 = { x: 1 }; return a1.x + 10; diff --git a/tests/baselines/reference/extractFunction/extractFunction21.js b/tests/baselines/reference/extractFunction/extractFunction21.js index 4454f36ac62a0..08c4512fee7c7 100644 --- a/tests/baselines/reference/extractFunction/extractFunction21.js +++ b/tests/baselines/reference/extractFunction/extractFunction21.js @@ -20,6 +20,7 @@ function foo() { x = /*RENAME*/newFunction(x); return; } + function newFunction(x) { x++; return x; diff --git a/tests/baselines/reference/extractFunction/extractFunction21.ts b/tests/baselines/reference/extractFunction/extractFunction21.ts index 530a10bea9591..4adb05f3bf1ca 100644 --- a/tests/baselines/reference/extractFunction/extractFunction21.ts +++ b/tests/baselines/reference/extractFunction/extractFunction21.ts @@ -20,6 +20,7 @@ function foo() { x = /*RENAME*/newFunction(x); return; } + function newFunction(x: number) { x++; return x; diff --git a/tests/baselines/reference/extractFunction/extractFunction22.js b/tests/baselines/reference/extractFunction/extractFunction22.js index 60891105c6ece..0fb69c87b0439 100644 --- a/tests/baselines/reference/extractFunction/extractFunction22.js +++ b/tests/baselines/reference/extractFunction/extractFunction22.js @@ -26,6 +26,7 @@ function test() { return /*RENAME*/newFunction(); } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction22.ts b/tests/baselines/reference/extractFunction/extractFunction22.ts index 60891105c6ece..0fb69c87b0439 100644 --- a/tests/baselines/reference/extractFunction/extractFunction22.ts +++ b/tests/baselines/reference/extractFunction/extractFunction22.ts @@ -26,6 +26,7 @@ function test() { return /*RENAME*/newFunction(); } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction23.ts b/tests/baselines/reference/extractFunction/extractFunction23.ts index 3092d6490baaf..b3730a5b54feb 100644 --- a/tests/baselines/reference/extractFunction/extractFunction23.ts +++ b/tests/baselines/reference/extractFunction/extractFunction23.ts @@ -38,6 +38,7 @@ namespace NS { } function M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction24.js b/tests/baselines/reference/extractFunction/extractFunction24.js index dbac567afc6ea..2c1d353f51a30 100644 --- a/tests/baselines/reference/extractFunction/extractFunction24.js +++ b/tests/baselines/reference/extractFunction/extractFunction24.js @@ -38,6 +38,7 @@ function Outer() { } function M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction24.ts b/tests/baselines/reference/extractFunction/extractFunction24.ts index dbac567afc6ea..2c1d353f51a30 100644 --- a/tests/baselines/reference/extractFunction/extractFunction24.ts +++ b/tests/baselines/reference/extractFunction/extractFunction24.ts @@ -38,6 +38,7 @@ function Outer() { } function M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction26.js b/tests/baselines/reference/extractFunction/extractFunction26.js index c05af641d4b23..2c821c05ad107 100644 --- a/tests/baselines/reference/extractFunction/extractFunction26.js +++ b/tests/baselines/reference/extractFunction/extractFunction26.js @@ -26,6 +26,7 @@ class C { } M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction26.ts b/tests/baselines/reference/extractFunction/extractFunction26.ts index 37eba24bfdeae..300686c12abca 100644 --- a/tests/baselines/reference/extractFunction/extractFunction26.ts +++ b/tests/baselines/reference/extractFunction/extractFunction26.ts @@ -26,6 +26,7 @@ class C { } M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction27.js b/tests/baselines/reference/extractFunction/extractFunction27.js index 96bca6b24c55c..702127b9d76ca 100644 --- a/tests/baselines/reference/extractFunction/extractFunction27.js +++ b/tests/baselines/reference/extractFunction/extractFunction27.js @@ -29,6 +29,7 @@ class C { constructor() { } M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction27.ts b/tests/baselines/reference/extractFunction/extractFunction27.ts index 335d74e002d09..1acbe67707a30 100644 --- a/tests/baselines/reference/extractFunction/extractFunction27.ts +++ b/tests/baselines/reference/extractFunction/extractFunction27.ts @@ -29,6 +29,7 @@ class C { constructor() { } M3() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction28.js b/tests/baselines/reference/extractFunction/extractFunction28.js index a82b864448daf..cf0742626dd98 100644 --- a/tests/baselines/reference/extractFunction/extractFunction28.js +++ b/tests/baselines/reference/extractFunction/extractFunction28.js @@ -29,6 +29,7 @@ class C { M3() { } constructor() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction28.ts b/tests/baselines/reference/extractFunction/extractFunction28.ts index bde2661f934e8..f15d7956f1c00 100644 --- a/tests/baselines/reference/extractFunction/extractFunction28.ts +++ b/tests/baselines/reference/extractFunction/extractFunction28.ts @@ -29,6 +29,7 @@ class C { M3() { } constructor() { } } + function newFunction() { return 1; } diff --git a/tests/baselines/reference/extractFunction/extractFunction3.ts b/tests/baselines/reference/extractFunction/extractFunction3.ts index 9c4c1aaa9d7f5..7a481e76cfa16 100644 --- a/tests/baselines/reference/extractFunction/extractFunction3.ts +++ b/tests/baselines/reference/extractFunction/extractFunction3.ts @@ -73,6 +73,7 @@ namespace A { } } } + function* newFunction(z: number, foo: () => void) { let y = 5; yield z; diff --git a/tests/baselines/reference/extractFunction/extractFunction30.ts b/tests/baselines/reference/extractFunction/extractFunction30.ts index b57b48c30a9ff..f90548c333c61 100644 --- a/tests/baselines/reference/extractFunction/extractFunction30.ts +++ b/tests/baselines/reference/extractFunction/extractFunction30.ts @@ -14,6 +14,7 @@ function F() { function F() { /*RENAME*/newFunction(); } + function newFunction() { let t: T; } diff --git a/tests/baselines/reference/extractFunction/extractFunction31.ts b/tests/baselines/reference/extractFunction/extractFunction31.ts index d7252a14011b8..2dea17689b6fb 100644 --- a/tests/baselines/reference/extractFunction/extractFunction31.ts +++ b/tests/baselines/reference/extractFunction/extractFunction31.ts @@ -37,6 +37,7 @@ namespace N { f = /*RENAME*/newFunction(f); } } + function newFunction(f: () => number) { f = function(): number { return N.value; diff --git a/tests/baselines/reference/extractFunction/extractFunction32.ts b/tests/baselines/reference/extractFunction/extractFunction32.ts index 4070763b79f44..720d0b227b0b9 100644 --- a/tests/baselines/reference/extractFunction/extractFunction32.ts +++ b/tests/baselines/reference/extractFunction/extractFunction32.ts @@ -37,6 +37,7 @@ namespace N { /*RENAME*/newFunction(); } } + function newFunction() { var c = class { M() { diff --git a/tests/baselines/reference/extractFunction/extractFunction33.js b/tests/baselines/reference/extractFunction/extractFunction33.js index 46c0f176b561b..cc027a14b6c64 100644 --- a/tests/baselines/reference/extractFunction/extractFunction33.js +++ b/tests/baselines/reference/extractFunction/extractFunction33.js @@ -14,6 +14,7 @@ function F() { function F() { /*RENAME*/newFunction(); } + function newFunction() { function G() { } } diff --git a/tests/baselines/reference/extractFunction/extractFunction33.ts b/tests/baselines/reference/extractFunction/extractFunction33.ts index 46c0f176b561b..cc027a14b6c64 100644 --- a/tests/baselines/reference/extractFunction/extractFunction33.ts +++ b/tests/baselines/reference/extractFunction/extractFunction33.ts @@ -14,6 +14,7 @@ function F() { function F() { /*RENAME*/newFunction(); } + function newFunction() { function G() { } } diff --git a/tests/baselines/reference/extractFunction/extractFunction4.ts b/tests/baselines/reference/extractFunction/extractFunction4.ts index 4108976b6b3f1..46aad65c68c5b 100644 --- a/tests/baselines/reference/extractFunction/extractFunction4.ts +++ b/tests/baselines/reference/extractFunction/extractFunction4.ts @@ -81,6 +81,7 @@ namespace A { } } } + async function newFunction(z: number, z1: any, foo: () => void) { let y = 5; if (z) { diff --git a/tests/baselines/reference/extractFunction/extractFunction5.ts b/tests/baselines/reference/extractFunction/extractFunction5.ts index 3122ba24553cc..085a73fdf9362 100644 --- a/tests/baselines/reference/extractFunction/extractFunction5.ts +++ b/tests/baselines/reference/extractFunction/extractFunction5.ts @@ -89,6 +89,7 @@ namespace A { } } } + function newFunction(x: number, a: number) { let y = 5; let z = x; diff --git a/tests/baselines/reference/extractFunction/extractFunction6.ts b/tests/baselines/reference/extractFunction/extractFunction6.ts index a01cb25e06178..613635c658a47 100644 --- a/tests/baselines/reference/extractFunction/extractFunction6.ts +++ b/tests/baselines/reference/extractFunction/extractFunction6.ts @@ -93,6 +93,7 @@ namespace A { } } } + function newFunction(x: number, a: number) { let y = 5; let z = x; diff --git a/tests/baselines/reference/extractFunction/extractFunction7.ts b/tests/baselines/reference/extractFunction/extractFunction7.ts index 4111558904c83..0f57a0cfba879 100644 --- a/tests/baselines/reference/extractFunction/extractFunction7.ts +++ b/tests/baselines/reference/extractFunction/extractFunction7.ts @@ -103,6 +103,7 @@ namespace A { } } } + function newFunction(x: number, a: number) { let y = 5; let z = x; diff --git a/tests/baselines/reference/extractFunction/extractFunction9.ts b/tests/baselines/reference/extractFunction/extractFunction9.ts index 7db12096cbc62..3df391c1fae76 100644 --- a/tests/baselines/reference/extractFunction/extractFunction9.ts +++ b/tests/baselines/reference/extractFunction/extractFunction9.ts @@ -59,6 +59,7 @@ namespace A { } } } + function newFunction() { let a1: A.I = { x: 1 }; return a1.x + 10; diff --git a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js index b5e4bc76c6e2f..b10a04e9ef094 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js +++ b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.js @@ -12,6 +12,7 @@ var q = /*b*/ //c var q = /*b*/ //c /*d*/ /*RENAME*/newFunction() /*k*/ //l /*m*/; /*n*/ //o + function newFunction() { return 1 /*e*/ //f /*g*/ + /*h*/ //i diff --git a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts index b5e4bc76c6e2f..b10a04e9ef094 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_PreserveTrivia.ts @@ -12,6 +12,7 @@ var q = /*b*/ //c var q = /*b*/ //c /*d*/ /*RENAME*/newFunction() /*k*/ //l /*m*/; /*n*/ //o + function newFunction() { return 1 /*e*/ //f /*g*/ + /*h*/ //i diff --git a/tests/baselines/reference/extractFunction/extractFunction_RepeatedSubstitution.ts b/tests/baselines/reference/extractFunction/extractFunction_RepeatedSubstitution.ts index 68cc7d2248aee..52ccce68059d1 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_RepeatedSubstitution.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_RepeatedSubstitution.ts @@ -17,6 +17,7 @@ namespace X { export const j = 10; export const y = /*RENAME*/newFunction(); } + function newFunction() { return X.j * X.j; } diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js index 67b4f64290c45..e8250613625fa 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.js @@ -21,6 +21,7 @@ function f() { let x = /*RENAME*/newFunction(); return { x }; } + function newFunction() { let x; return x; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts index 67b4f64290c45..e8250613625fa 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_ShorthandProperty.ts @@ -21,6 +21,7 @@ function f() { let x = /*RENAME*/newFunction(); return { x }; } + function newFunction() { let x; return x; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js index 1da5a568333e0..a8629d2907c2c 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.js @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a) { const x = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts index f93f43ceebf84..c70dbe95c7b2b 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_NoType.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { const x = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts index ec846f7f28840..3c0912061aacf 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Const_Type.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { const x: number = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts index 50bad34efceff..06de0fd4f368a 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType1.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { let x: 0o10 | 10 | 0b10 = 10; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts index 2df8ab67e9fe2..4679b89f06839 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_LiteralType2.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { let x: "a" | 'b' = 'a'; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js index 2f298c8719f6a..a86870d72a311 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.js @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a) { let x = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts index e4afefa9da633..9b711765c95fe 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_NoType.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { let x = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts index 795effbeb7eaa..652faab489005 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_Type.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { let x: number = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts index 53599c26d08b4..71c4d9b79ff7d 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Let_TypeWithComments.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { let x: /*A*/ "a" /*B*/ | /*C*/ 'b' /*D*/ = 'a'; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js index c36557847f79e..5de10b2cf76b1 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.js @@ -30,6 +30,7 @@ function f() { ({ x, y, a } = /*RENAME*/newFunction(a)); a; x; y; } + function newFunction(a) { const x = 1; let y = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts index eaeb781bc484a..d4da8ffca7b55 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed1.ts @@ -30,6 +30,7 @@ function f() { ({ x, y, a } = /*RENAME*/newFunction(a)); a; x; y; } + function newFunction(a: number) { const x = 1; let y = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js index 2d1151a549c8d..e1526a77ffdbf 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.js @@ -30,6 +30,7 @@ function f() { ({ x, y, a } = /*RENAME*/newFunction(a)); a; x; y; } + function newFunction(a) { var x = 1; let y = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts index 9466b5dc37f82..ec3d62c039b73 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed2.ts @@ -30,6 +30,7 @@ function f() { ({ x, y, a } = /*RENAME*/newFunction(a)); a; x; y; } + function newFunction(a: number) { var x = 1; let y = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts index 604d2a33c43ce..b2c53e3f1602c 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Mixed3.ts @@ -30,6 +30,7 @@ function f() { ({ x, y, a } = /*RENAME*/newFunction(a)); a; x; y; } + function newFunction(a: number) { let x: number = 1; let y = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts index 0cf71e45e2836..b76bf6c499961 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_UnionUndefined.ts @@ -33,6 +33,7 @@ function f() { ({ x, y, z, a } = /*RENAME*/newFunction(a)); a; x; y; z; } + function newFunction(a: number) { let x: number | undefined = 1; let y: undefined | number = 2; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js index 25e910713d8ab..6a7b821e5b14d 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.js @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a) { var x = 1; a++; diff --git a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts index e215e3d097805..e9cbe7ad3452a 100644 --- a/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts +++ b/tests/baselines/reference/extractFunction/extractFunction_VariableDeclaration_Writes_Var.ts @@ -27,6 +27,7 @@ function f() { ({ x, a } = /*RENAME*/newFunction(a)); a; x; } + function newFunction(a: number) { var x = 1; a++; diff --git a/tests/cases/fourslash/extract-method-empty-namespace.ts b/tests/cases/fourslash/extract-method-empty-namespace.ts index bef4cdd12fe4e..1655efccbb83e 100644 --- a/tests/cases/fourslash/extract-method-empty-namespace.ts +++ b/tests/cases/fourslash/extract-method-empty-namespace.ts @@ -12,6 +12,7 @@ edit.applyRefactor({ newContent: `function f() { /*RENAME*/newFunction(); } + function newFunction() { namespace N { } } diff --git a/tests/cases/fourslash/extract-method-formatting.ts b/tests/cases/fourslash/extract-method-formatting.ts index d4c2836e815e6..d1f550f794e86 100644 --- a/tests/cases/fourslash/extract-method-formatting.ts +++ b/tests/cases/fourslash/extract-method-formatting.ts @@ -13,6 +13,7 @@ edit.applyRefactor({ newContent: `function f(x: number): number { return /*RENAME*/newFunction(x); } + function newFunction(x: number) { switch (x) { case 0: diff --git a/tests/cases/fourslash/extract-method-uniqueName.ts b/tests/cases/fourslash/extract-method-uniqueName.ts index da4c68cfb7e1d..a02b2c5ec9646 100644 --- a/tests/cases/fourslash/extract-method-uniqueName.ts +++ b/tests/cases/fourslash/extract-method-uniqueName.ts @@ -13,6 +13,7 @@ edit.applyRefactor({ newContent: `// newFunction /*RENAME*/newFunction_1(); + function newFunction_1() { 1 + 1; } diff --git a/tests/cases/fourslash/extract-method10.ts b/tests/cases/fourslash/extract-method10.ts index ed92e6b06ac8d..d2b9aeb0123bf 100644 --- a/tests/cases/fourslash/extract-method10.ts +++ b/tests/cases/fourslash/extract-method10.ts @@ -11,6 +11,7 @@ edit.applyRefactor({ newContent: `export {}; // Make this a module (x => x)(/*RENAME*/newFunction())(1); + function newFunction(): (x: any) => any { return x => x; } diff --git a/tests/cases/fourslash/extract-method14.ts b/tests/cases/fourslash/extract-method14.ts index ddfd8cbcbd6e1..11ea1f1b3fde4 100644 --- a/tests/cases/fourslash/extract-method14.ts +++ b/tests/cases/fourslash/extract-method14.ts @@ -22,6 +22,7 @@ edit.applyRefactor({ ({ __return, i } = /*RENAME*/newFunction(i)); return __return; } + function newFunction(i) { return { __return: i++, i }; } diff --git a/tests/cases/fourslash/extract-method15.ts b/tests/cases/fourslash/extract-method15.ts index e46ff39ad6a49..1b33a46b9a43f 100644 --- a/tests/cases/fourslash/extract-method15.ts +++ b/tests/cases/fourslash/extract-method15.ts @@ -18,6 +18,7 @@ edit.applyRefactor({ var i = 10; i = /*RENAME*/newFunction(i); } + function newFunction(i: number) { i++; return i; diff --git a/tests/cases/fourslash/extract-method18.ts b/tests/cases/fourslash/extract-method18.ts index d53e79f493000..0a488a04106c9 100644 --- a/tests/cases/fourslash/extract-method18.ts +++ b/tests/cases/fourslash/extract-method18.ts @@ -18,6 +18,7 @@ edit.applyRefactor({ const x = { m: 1 }; /*RENAME*/newFunction(x); } + function newFunction(x: { m: number; }) { x.m = 3; } diff --git a/tests/cases/fourslash/extract-method2.ts b/tests/cases/fourslash/extract-method2.ts index 7f197d4775b0d..419d63790756a 100644 --- a/tests/cases/fourslash/extract-method2.ts +++ b/tests/cases/fourslash/extract-method2.ts @@ -24,6 +24,7 @@ edit.applyRefactor({ } } } + function newFunction(m: number, j: string, k: { x: string; }) { return m + j + k; } diff --git a/tests/cases/fourslash/extract-method24.ts b/tests/cases/fourslash/extract-method24.ts index 8c750edd9f906..66ca5ecb2274b 100644 --- a/tests/cases/fourslash/extract-method24.ts +++ b/tests/cases/fourslash/extract-method24.ts @@ -17,6 +17,7 @@ edit.applyRefactor({ let x = 0; console.log(/*RENAME*/newFunction(a, x)); } + function newFunction(a: number[], x: number): any { return a[x]; } diff --git a/tests/cases/fourslash/extract-method7.ts b/tests/cases/fourslash/extract-method7.ts index 2998b6bbee31c..38bc86cb5dc54 100644 --- a/tests/cases/fourslash/extract-method7.ts +++ b/tests/cases/fourslash/extract-method7.ts @@ -14,6 +14,7 @@ edit.applyRefactor({ newContent: `function fn(x = /*RENAME*/newFunction()) { } + function newFunction() { return 3; } From f35764d4ecf69e5c6be292fa7018fdc6f27f70c9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 12 Oct 2017 14:28:34 -0700 Subject: [PATCH 158/246] Fix duplicated JSDoc comments Incorporate suppressLeadingAndTrailingTrivia just added by @amcasey. --- src/services/refactors/annotateWithTypeFromJSDoc.ts | 10 +++++++--- tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts | 3 --- tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts | 1 - tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index bc6dcd073bf49..1e32df4a51a02 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -62,14 +62,16 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(token, isDeclarationWithType); - const jsdocType = getJSDocReturnType(decl) || getJSDocType(decl); + const jsdocType = getJSDocType(decl); if (!decl || !jsdocType || decl.type) { Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); return undefined; } const changeTracker = textChanges.ChangeTracker.fromContext(context); - changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, addType(decl, transformJSDocType(jsdocType) as TypeNode)); + const declarationWithType = addType(decl, transformJSDocType(jsdocType) as TypeNode); + suppressLeadingAndTrailingTrivia(declarationWithType); + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, declarationWithType); return { edits: changeTracker.getChanges(), renameFilename: undefined, @@ -87,7 +89,9 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(token, isFunctionLikeDeclaration); const changeTracker = textChanges.ChangeTracker.fromContext(context); - changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, addTypesToFunctionLike(decl)); + const functionWithType = addTypesToFunctionLike(decl); + suppressLeadingAndTrailingTrivia(functionWithType); + changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, functionWithType); return { edits: changeTracker.getChanges(), renameFilename: undefined, diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts index c3c1aad5a90ef..e541bad4e4f29 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts @@ -10,9 +10,6 @@ verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `class C { - /** - * @return {...*} - */ /** * @return {...*} */ diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts index 1f15bf5992460..83e0888ddf589 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts @@ -9,7 +9,6 @@ verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `class C { - /** @type {number | null} */ /** @type {number | null} */ p: number | null = null; }`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts index 91bc1523ea301..f6fce6c449f86 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts @@ -9,7 +9,6 @@ verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `declare class C { - /** @type {number | null} */ /** @type {number | null} */ p: number | null; }`, 'Annotate with type from JSDoc', 'annotate'); From de0e475c64a5dbba72d22c0edf6ce5552a5a0ebe Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 12 Oct 2017 15:05:04 -0700 Subject: [PATCH 159/246] Recreate old decorator metadata behavior (#19089) * Emulate pre 2.4 metadata behavior of eliding null and undefined from unions without strictNullChecks * Accept baseline * Update comment * Update for second old baseline * Respect strict --- src/compiler/transformers/ts.ts | 14 ++++++-- .../decoratorMetadataNoStrictNull.js | 32 +++++++++++++++++++ .../decoratorMetadataNoStrictNull.symbols | 18 +++++++++++ .../decoratorMetadataNoStrictNull.types | 20 ++++++++++++ .../reference/metadataOfClassFromAlias.js | 2 +- .../reference/metadataOfUnionWithNull.js | 16 +++++----- .../compiler/decoratorMetadataNoStrictNull.ts | 8 +++++ 7 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 tests/baselines/reference/decoratorMetadataNoStrictNull.js create mode 100644 tests/baselines/reference/decoratorMetadataNoStrictNull.symbols create mode 100644 tests/baselines/reference/decoratorMetadataNoStrictNull.types create mode 100644 tests/cases/compiler/decoratorMetadataNoStrictNull.ts diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index e67918fd696a4..ba4b5fcdf521e 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -45,6 +45,7 @@ namespace ts { const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); + const strictNullChecks = typeof compilerOptions.strictNullChecks === "undefined" ? compilerOptions.strict : compilerOptions.strictNullChecks; const languageVersion = getEmitScriptTarget(compilerOptions); const moduleKind = getEmitModuleKind(compilerOptions); @@ -1869,7 +1870,16 @@ namespace ts { // Note when updating logic here also update getEntityNameForDecoratorMetadata // so that aliases can be marked as referenced let serializedUnion: SerializedTypeNode; - for (const typeNode of node.types) { + for (let typeNode of node.types) { + while (typeNode.kind === SyntaxKind.ParenthesizedType) { + typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be + } + if (typeNode.kind === SyntaxKind.NeverKeyword) { + continue; // Always elide `never` from the union/intersection if possible + } + if (!strictNullChecks && (typeNode.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks + } const serializedIndividual = serializeTypeNode(typeNode); if (isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") { @@ -1893,7 +1903,7 @@ namespace ts { } // If we were able to find common type, use it - return serializedUnion; + return serializedUnion || createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never } /** diff --git a/tests/baselines/reference/decoratorMetadataNoStrictNull.js b/tests/baselines/reference/decoratorMetadataNoStrictNull.js new file mode 100644 index 0000000000000..dada68f0960cb --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataNoStrictNull.js @@ -0,0 +1,32 @@ +//// [decoratorMetadataNoStrictNull.ts] +const dec = (obj: {}, prop: string) => undefined + +class Foo { + @dec public foo: string | null; + @dec public bar: string; +} + +//// [decoratorMetadataNoStrictNull.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var dec = function (obj, prop) { return undefined; }; +var Foo = /** @class */ (function () { + function Foo() { + } + __decorate([ + dec, + __metadata("design:type", String) + ], Foo.prototype, "foo"); + __decorate([ + dec, + __metadata("design:type", String) + ], Foo.prototype, "bar"); + return Foo; +}()); diff --git a/tests/baselines/reference/decoratorMetadataNoStrictNull.symbols b/tests/baselines/reference/decoratorMetadataNoStrictNull.symbols new file mode 100644 index 0000000000000..32a6d08f02425 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataNoStrictNull.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts === +const dec = (obj: {}, prop: string) => undefined +>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5)) +>obj : Symbol(obj, Decl(decoratorMetadataNoStrictNull.ts, 0, 13)) +>prop : Symbol(prop, Decl(decoratorMetadataNoStrictNull.ts, 0, 21)) +>undefined : Symbol(undefined) + +class Foo { +>Foo : Symbol(Foo, Decl(decoratorMetadataNoStrictNull.ts, 0, 48)) + + @dec public foo: string | null; +>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5)) +>foo : Symbol(Foo.foo, Decl(decoratorMetadataNoStrictNull.ts, 2, 11)) + + @dec public bar: string; +>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5)) +>bar : Symbol(Foo.bar, Decl(decoratorMetadataNoStrictNull.ts, 3, 33)) +} diff --git a/tests/baselines/reference/decoratorMetadataNoStrictNull.types b/tests/baselines/reference/decoratorMetadataNoStrictNull.types new file mode 100644 index 0000000000000..981efe6e50bd7 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadataNoStrictNull.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts === +const dec = (obj: {}, prop: string) => undefined +>dec : (obj: {}, prop: string) => any +>(obj: {}, prop: string) => undefined : (obj: {}, prop: string) => any +>obj : {} +>prop : string +>undefined : undefined + +class Foo { +>Foo : Foo + + @dec public foo: string | null; +>dec : (obj: {}, prop: string) => any +>foo : string +>null : null + + @dec public bar: string; +>dec : (obj: {}, prop: string) => any +>bar : string +} diff --git a/tests/baselines/reference/metadataOfClassFromAlias.js b/tests/baselines/reference/metadataOfClassFromAlias.js index 307702cd7bfb2..77ae5c3389881 100644 --- a/tests/baselines/reference/metadataOfClassFromAlias.js +++ b/tests/baselines/reference/metadataOfClassFromAlias.js @@ -43,7 +43,7 @@ var ClassA = /** @class */ (function () { } __decorate([ annotation(), - __metadata("design:type", Object) + __metadata("design:type", auxiliry_1.SomeClass) ], ClassA.prototype, "array", void 0); return ClassA; }()); diff --git a/tests/baselines/reference/metadataOfUnionWithNull.js b/tests/baselines/reference/metadataOfUnionWithNull.js index 80d24709b73ae..7bf9aeb865057 100644 --- a/tests/baselines/reference/metadataOfUnionWithNull.js +++ b/tests/baselines/reference/metadataOfUnionWithNull.js @@ -63,15 +63,15 @@ var B = /** @class */ (function () { } __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", String) ], B.prototype, "x"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", Boolean) ], B.prototype, "y"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", String) ], B.prototype, "z"); __decorate([ PropDeco, @@ -87,11 +87,11 @@ var B = /** @class */ (function () { ], B.prototype, "c"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", void 0) ], B.prototype, "d"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", typeof Symbol === "function" ? Symbol : Object) ], B.prototype, "e"); __decorate([ PropDeco, @@ -99,15 +99,15 @@ var B = /** @class */ (function () { ], B.prototype, "f"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", A) ], B.prototype, "g"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", B) ], B.prototype, "h"); __decorate([ PropDeco, - __metadata("design:type", Object) + __metadata("design:type", typeof Symbol === "function" ? Symbol : Object) ], B.prototype, "j"); return B; }()); diff --git a/tests/cases/compiler/decoratorMetadataNoStrictNull.ts b/tests/cases/compiler/decoratorMetadataNoStrictNull.ts new file mode 100644 index 0000000000000..4ac608ebd7445 --- /dev/null +++ b/tests/cases/compiler/decoratorMetadataNoStrictNull.ts @@ -0,0 +1,8 @@ +// @experimentalDecorators: true +// @emitDecoratorMetadata: true +const dec = (obj: {}, prop: string) => undefined + +class Foo { + @dec public foo: string | null; + @dec public bar: string; +} \ No newline at end of file From 6099b09a6ebf73dbd6ce9c10ef6f1e6b70c0e9b1 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 13 Oct 2017 07:17:17 -0700 Subject: [PATCH 160/246] Create source files lazily in tests (#19143) --- src/harness/harness.ts | 10 +++++++--- src/harness/unittests/moduleResolution.ts | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index a0fb88213edde..a3789eb9ebf8f 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -844,9 +844,7 @@ namespace Harness { export const es2015DefaultLibFileName = "lib.es2015.d.ts"; // Cache of lib files from "built/local" - const libFileNameSourceFileMap = ts.createMapFromTemplate({ - [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) - }); + let libFileNameSourceFileMap: ts.Map | undefined; // Cache of lib files from "tests/lib/" const testLibFileNameSourceFileMap = ts.createMap(); @@ -857,6 +855,12 @@ namespace Harness { return undefined; } + if (!libFileNameSourceFileMap) { + libFileNameSourceFileMap = ts.createMapFromTemplate({ + [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) + }); + } + let sourceFile = libFileNameSourceFileMap.get(fileName); if (!sourceFile) { libFileNameSourceFileMap.set(fileName, sourceFile = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName), ts.ScriptTarget.Latest)); diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index 0acbe9450bbe1..32301d6dccfd3 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -392,7 +392,7 @@ export = C; }); describe("Files with different casing", () => { - const library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5); + let library: SourceFile; function test(files: Map, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void { const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); if (!useCaseSensitiveFileNames) { @@ -406,6 +406,9 @@ export = C; const host: CompilerHost = { getSourceFile: (fileName: string, languageVersion: ScriptTarget) => { if (fileName === "lib.d.ts") { + if (!library) { + library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5); + } return library; } const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName))); From c3a2dc3f44e47a70f01c91fc4b29876bd7fa43d1 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 13 Oct 2017 16:10:06 +0000 Subject: [PATCH 161/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17108 ++++++++-------- .../diagnosticMessages.generated.json.lcl | 17108 ++++++++-------- 2 files changed, 17186 insertions(+), 17030 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index ccfe22a59ffaa..3c83950d4f32c 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8516 +1,8594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - 或 <语言>-<区域> 形式。例如“{0}”或“{1}”。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - 类型。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()"。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + 或 <语言>-<区域> 形式。例如“{0}”或“{1}”。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + 类型。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()"。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 0db33b6bbe94c..c25043edfa592 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8516 +1,8594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - 또는 - 형식이어야 합니다. 예를 들어 '{0}' 또는 '{1}'입니다.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - 형식이어야 합니다.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()'를 사용하세요.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + 또는 - 형식이어야 합니다. 예를 들어 '{0}' 또는 '{1}'입니다.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + 형식이어야 합니다.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()'를 사용하세요.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c83daa64811c7705318de6c35d23f76a9c24c744 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 13 Oct 2017 09:38:01 -0700 Subject: [PATCH 162/246] JSDoc->type refactor:Renames+improve never handling --- .../refactors/annotateWithTypeFromJSDoc.ts | 66 +++++++++---------- .../fourslash/annotateWithTypeFromJSDoc5.ts | 1 - .../fourslash/annotateWithTypeFromJSDoc6.ts | 1 - 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 1e32df4a51a02..52d3fe30e8d60 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -32,24 +32,25 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(node, isDeclarationWithType); - if (decl && !decl.type) { - const type = getJSDocType(decl); - const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); - const annotate = (isFunctionWithJSDoc || type && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : - type ? annotateTypeFromJSDoc : - undefined; - if (annotate) { - return [{ - name: annotate.name, - description: annotate.description, - actions: [ - { - description: annotate.description, - name: actionName - } - ] - }]; - } + if (!decl || decl.type) { + return undefined; + } + const jsdocType = getJSDocType(decl); + const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); + const refactor = (isFunctionWithJSDoc || jsdocType && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : + jsdocType ? annotateTypeFromJSDoc : + undefined; + if (refactor) { + return [{ + name: refactor.name, + description: refactor.description, + actions: [ + { + description: refactor.description, + name: actionName + } + ] + }]; } } @@ -64,8 +65,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const decl = findAncestor(token, isDeclarationWithType); const jsdocType = getJSDocType(decl); if (!decl || !jsdocType || decl.type) { - Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); - return undefined; + return Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`); } const changeTracker = textChanges.ChangeTracker.fromContext(context); @@ -128,7 +128,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.SetAccessor: return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body); default: - return Debug.fail(`Unexpected SyntaxKind: ${(decl as any).kind}`); + return Debug.assertNever(decl,`Unexpected SyntaxKind: ${(decl as any).kind}`); } } @@ -155,42 +155,42 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.JSDocUnknownType: return createTypeReferenceNode("any", emptyArray); case SyntaxKind.JSDocOptionalType: - return visitJSDocOptionalType(node as JSDocOptionalType); + return transformJSDocOptionalType(node as JSDocOptionalType); case SyntaxKind.JSDocNonNullableType: return transformJSDocType((node as JSDocNonNullableType).type); case SyntaxKind.JSDocNullableType: - return visitJSDocNullableType(node as JSDocNullableType); + return transformJSDocNullableType(node as JSDocNullableType); case SyntaxKind.JSDocVariadicType: - return visitJSDocVariadicType(node as JSDocVariadicType); + return transformJSDocVariadicType(node as JSDocVariadicType); case SyntaxKind.JSDocFunctionType: - return visitJSDocFunctionType(node as JSDocFunctionType); + return transformJSDocFunctionType(node as JSDocFunctionType); case SyntaxKind.Parameter: - return visitJSDocParameter(node as ParameterDeclaration); + return transformJSDocParameter(node as ParameterDeclaration); case SyntaxKind.TypeReference: - return visitJSDocTypeReference(node as TypeReferenceNode); + return transformJSDocTypeReference(node as TypeReferenceNode); default: return visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode; } } - function visitJSDocOptionalType(node: JSDocOptionalType) { + function transformJSDocOptionalType(node: JSDocOptionalType) { return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("undefined", emptyArray)]); } - function visitJSDocNullableType(node: JSDocNullableType) { + function transformJSDocNullableType(node: JSDocNullableType) { return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("null", emptyArray)]); } - function visitJSDocVariadicType(node: JSDocVariadicType) { + function transformJSDocVariadicType(node: JSDocVariadicType) { return createArrayTypeNode(visitNode(node.type, transformJSDocType)); } - function visitJSDocFunctionType(node: JSDocFunctionType) { + function transformJSDocFunctionType(node: JSDocFunctionType) { const parameters = node.parameters && node.parameters.map(transformJSDocType); return createFunctionTypeNode(emptyArray, parameters as ParameterDeclaration[], node.type); } - function visitJSDocParameter(node: ParameterDeclaration) { + function transformJSDocParameter(node: ParameterDeclaration) { const index = node.parent.parameters.indexOf(node); const isRest = node.type.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; const name = node.name || (isRest ? "rest" : "arg" + index); @@ -198,7 +198,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer); } - function visitJSDocTypeReference(node: TypeReferenceNode) { + function transformJSDocTypeReference(node: TypeReferenceNode) { let name = node.typeName; let args = node.typeArguments; if (isIdentifier(node.typeName)) { diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts index 83e0888ddf589..1ae2949ef3ca4 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts @@ -5,7 +5,6 @@ //// /*1*/p = null ////} -// NOTE: The duplicated comment is unintentional but needs a serious fix in trivia handling verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `class C { diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts index f6fce6c449f86..53e8170533df6 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts @@ -5,7 +5,6 @@ //// /*1*/p; ////} -// NOTE: The duplicated comment is unintentional but needs a serious fix in trivia handling verify.applicableRefactorAvailableAtMarker('1'); verify.fileAfterApplyingRefactorAtMarker('1', `declare class C { From 84e3507151a80334e1e1ecfefe6141f77e3e3b6e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 13 Oct 2017 09:45:41 -0700 Subject: [PATCH 163/246] return more Debug.fails instead of undefined. --- src/services/refactors/annotateWithTypeFromJSDoc.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 52d3fe30e8d60..17d910b309162 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -56,8 +56,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { function getEditsForAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { if (actionName !== action) { - Debug.fail(`actionName !== action: ${actionName} !== ${action}`); - return undefined; + return Debug.fail(`actionName !== action: ${actionName} !== ${action}`); } const sourceFile = context.file; @@ -81,8 +80,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { function getEditsForFunctionAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { if (actionName !== action) { - Debug.fail(`actionName !== action: ${actionName} !== ${action}`); - return undefined; + return Debug.fail(`actionName !== action: ${actionName} !== ${action}`); } const sourceFile = context.file; @@ -141,8 +139,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.PropertyDeclaration: return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer); default: - Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`); - return undefined; + return Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`); } } From 4cf06bbb02a2835021542571ddadfc0cf68cb3f6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 13 Oct 2017 10:02:04 -0700 Subject: [PATCH 164/246] Fix spacing lint --- src/services/refactors/annotateWithTypeFromJSDoc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 17d910b309162..60c0517f68113 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -126,7 +126,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.SetAccessor: return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body); default: - return Debug.assertNever(decl,`Unexpected SyntaxKind: ${(decl as any).kind}`); + return Debug.assertNever(decl, `Unexpected SyntaxKind: ${(decl as any).kind}`); } } From 769d202d4caaa7036f004c5ce27f961f0d70b12a Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 13 Oct 2017 14:53:52 -0700 Subject: [PATCH 165/246] In getContextuallyTypedParameterType, skip a `this` parameter when counting parameter index (#19155) --- src/compiler/checker.ts | 9 +++++++-- .../fourslash/quickInfoParameter_skipThisParameter.ts | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/quickInfoParameter_skipThisParameter.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9347329e624b2..4f144f3ff9b21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13182,7 +13182,7 @@ namespace ts { } // Return contextual type of parameter or undefined if no contextual type is available - function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type { + function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type | undefined { const func = parameter.parent; if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const iife = getImmediatelyInvokedFunctionExpression(func); @@ -13208,7 +13208,12 @@ namespace ts { if (contextualSignature) { const funcHasRestParameters = hasRestParameter(func); const len = func.parameters.length - (funcHasRestParameters ? 1 : 0); - const indexOfParameter = indexOf(func.parameters, parameter); + let indexOfParameter = indexOf(func.parameters, parameter); + if (getThisParameter(func) !== undefined && !contextualSignature.thisParameter) { + Debug.assert(indexOfParameter !== 0); // Otherwise we should not have called `getContextuallyTypedParameterType`. + indexOfParameter -= 1; + } + if (indexOfParameter < len) { return getTypeAtPosition(contextualSignature, indexOfParameter); } diff --git a/tests/cases/fourslash/quickInfoParameter_skipThisParameter.ts b/tests/cases/fourslash/quickInfoParameter_skipThisParameter.ts new file mode 100644 index 0000000000000..15e28aca0b5da --- /dev/null +++ b/tests/cases/fourslash/quickInfoParameter_skipThisParameter.ts @@ -0,0 +1,6 @@ +/// + +////function f(cb: (x: number) => void) {} +////f(function(this: any, /**/x) {}); + +verify.quickInfoAt("", "(parameter) x: number"); From fadf4914bbfe184b37cdd0a923782730ab8b99c4 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 13 Oct 2017 22:10:24 +0000 Subject: [PATCH 166/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17126 ++++++++-------- .../diagnosticMessages.generated.json.lcl | 17126 ++++++++-------- .../diagnosticMessages.generated.json.lcl | 17108 +++++++-------- .../diagnosticMessages.generated.json.lcl | 17034 +++++++-------- .../diagnosticMessages.generated.json.lcl | 17106 +++++++-------- 5 files changed, 42945 insertions(+), 42555 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6a727b8b8e855..075923ea43857 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8525 +1,8603 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - nebo . Třeba {0} nebo {1}.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - .]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ().]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + nebo . Třeba {0} nebo {1}.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + .]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ().]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9e8be1a2bfa7c..026f10b37be90 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8525 +1,8603 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - ou -. Par exemple, '{0}' ou '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - global.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' à la place.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + ou -. Par exemple, '{0}' ou '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + global.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' à la place.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6bb0ed245b9da..b978802c56409 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8516 +1,8594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - o -, ad esempio, '{0}' o '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - .]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + o -, ad esempio, '{0}' o '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + .]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index c75652ece470b..3a8512e54b238 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8479 +1,8557 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - lub -. Na przykład „{0}” lub „{1}”.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - .]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()”.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + lub -. Na przykład „{0}” lub „{1}”.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + .]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()”.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 780f933d28b61..aac4d18cd6799 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8515 +1,8593 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - или <язык>–<территория>. Например, "{0}" или "{1}".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - .]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + или <язык>–<территория>. Например, "{0}" или "{1}".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + .]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 16f7f6f2e94c489780efed8227adeffc37d22769 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Oct 2017 14:33:53 -0700 Subject: [PATCH 167/246] Added test case. --- .../compiler/taggedTemplatesInDifferentScopes.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/cases/compiler/taggedTemplatesInDifferentScopes.ts diff --git a/tests/cases/compiler/taggedTemplatesInDifferentScopes.ts b/tests/cases/compiler/taggedTemplatesInDifferentScopes.ts new file mode 100644 index 0000000000000..836a3535029fd --- /dev/null +++ b/tests/cases/compiler/taggedTemplatesInDifferentScopes.ts @@ -0,0 +1,15 @@ +export function tag(parts: TemplateStringsArray, ...values: any[]) { + return parts[0]; +} +function foo() { + tag `foo`; + tag `foo2`; +} + +function bar() { + tag `bar`; + tag `bar2`; +} + +foo(); +bar(); From 50085bab27b9b154a0ba3d618950c15eb01b8c3e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Oct 2017 15:25:04 -0700 Subject: [PATCH 168/246] Create truly unique names for tagged template strings. --- src/compiler/transformers/es2015.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index d5ce2bdc3a413..a1e524801722c 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3676,7 +3676,8 @@ namespace ts { // Do not do this in the global scope, as any variable we currently generate could conflict with // variables from outside of the current compilation. In the future, we can revisit this behavior. if (isExternalModule(currentSourceFile)) { - const tempVar = createTempVariable(recordTaggedTemplateString); + const tempVar = createUniqueName("templateObject"); + recordTaggedTemplateString(tempVar); templateArguments[0] = createLogicalOr( tempVar, createAssignment( From 258c4e0bccc13741b3b52677984dabffeb6282b2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 13 Oct 2017 15:27:16 -0700 Subject: [PATCH 169/246] Accepted baselines. --- tests/baselines/reference/importHelpers.js | 4 +- .../taggedTemplateWithoutDeclaredHelper.js | 4 +- .../taggedTemplatesInDifferentScopes.js | 44 +++++++++++++++++ .../taggedTemplatesInDifferentScopes.symbols | 36 ++++++++++++++ .../taggedTemplatesInDifferentScopes.types | 48 +++++++++++++++++++ .../taggedTemplatesInModuleAndGlobal.js | 4 +- 6 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/taggedTemplatesInDifferentScopes.js create mode 100644 tests/baselines/reference/taggedTemplatesInDifferentScopes.symbols create mode 100644 tests/baselines/reference/taggedTemplatesInDifferentScopes.types diff --git a/tests/baselines/reference/importHelpers.js b/tests/baselines/reference/importHelpers.js index 7bdd660a9ae7d..cf427400ab1a0 100644 --- a/tests/baselines/reference/importHelpers.js +++ b/tests/baselines/reference/importHelpers.js @@ -83,8 +83,8 @@ var C = /** @class */ (function () { function id(x) { return x; } -exports.result = id(_a || (_a = tslib_1.__makeTemplateObject(["hello world"], ["hello world"]))); -var _a; +exports.result = id(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["hello world"], ["hello world"]))); +var templateObject_1; //// [script.js] var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || diff --git a/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.js b/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.js index 453b35d98ba84..19006f93b3e05 100755 --- a/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.js +++ b/tests/baselines/reference/taggedTemplateWithoutDeclaredHelper.js @@ -18,5 +18,5 @@ var tslib_1 = require("tslib"); function id(x) { return x; } -exports.result = id(_a || (_a = tslib_1.__makeTemplateObject(["hello world"], ["hello world"]))); -var _a; +exports.result = id(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["hello world"], ["hello world"]))); +var templateObject_1; diff --git a/tests/baselines/reference/taggedTemplatesInDifferentScopes.js b/tests/baselines/reference/taggedTemplatesInDifferentScopes.js new file mode 100644 index 0000000000000..e43c9a1e5e226 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesInDifferentScopes.js @@ -0,0 +1,44 @@ +//// [taggedTemplatesInDifferentScopes.ts] +export function tag(parts: TemplateStringsArray, ...values: any[]) { + return parts[0]; +} +function foo() { + tag `foo`; + tag `foo2`; +} + +function bar() { + tag `bar`; + tag `bar2`; +} + +foo(); +bar(); + + +//// [taggedTemplatesInDifferentScopes.js] +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +exports.__esModule = true; +function tag(parts) { + var values = []; + for (var _i = 1; _i < arguments.length; _i++) { + values[_i - 1] = arguments[_i]; + } + return parts[0]; +} +exports.tag = tag; +function foo() { + tag(templateObject_1 || (templateObject_1 = __makeTemplateObject(["foo"], ["foo"]))); + tag(templateObject_2 || (templateObject_2 = __makeTemplateObject(["foo2"], ["foo2"]))); +} +function bar() { + tag(templateObject_3 || (templateObject_3 = __makeTemplateObject(["bar"], ["bar"]))); + tag(templateObject_4 || (templateObject_4 = __makeTemplateObject(["bar2"], ["bar2"]))); +} +foo(); +bar(); +var templateObject_1, templateObject_2, templateObject_3, templateObject_4; diff --git a/tests/baselines/reference/taggedTemplatesInDifferentScopes.symbols b/tests/baselines/reference/taggedTemplatesInDifferentScopes.symbols new file mode 100644 index 0000000000000..071616b85f17a --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesInDifferentScopes.symbols @@ -0,0 +1,36 @@ +=== tests/cases/compiler/taggedTemplatesInDifferentScopes.ts === +export function tag(parts: TemplateStringsArray, ...values: any[]) { +>tag : Symbol(tag, Decl(taggedTemplatesInDifferentScopes.ts, 0, 0)) +>parts : Symbol(parts, Decl(taggedTemplatesInDifferentScopes.ts, 0, 20)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.d.ts, --, --)) +>values : Symbol(values, Decl(taggedTemplatesInDifferentScopes.ts, 0, 48)) + + return parts[0]; +>parts : Symbol(parts, Decl(taggedTemplatesInDifferentScopes.ts, 0, 20)) +} +function foo() { +>foo : Symbol(foo, Decl(taggedTemplatesInDifferentScopes.ts, 2, 1)) + + tag `foo`; +>tag : Symbol(tag, Decl(taggedTemplatesInDifferentScopes.ts, 0, 0)) + + tag `foo2`; +>tag : Symbol(tag, Decl(taggedTemplatesInDifferentScopes.ts, 0, 0)) +} + +function bar() { +>bar : Symbol(bar, Decl(taggedTemplatesInDifferentScopes.ts, 6, 1)) + + tag `bar`; +>tag : Symbol(tag, Decl(taggedTemplatesInDifferentScopes.ts, 0, 0)) + + tag `bar2`; +>tag : Symbol(tag, Decl(taggedTemplatesInDifferentScopes.ts, 0, 0)) +} + +foo(); +>foo : Symbol(foo, Decl(taggedTemplatesInDifferentScopes.ts, 2, 1)) + +bar(); +>bar : Symbol(bar, Decl(taggedTemplatesInDifferentScopes.ts, 6, 1)) + diff --git a/tests/baselines/reference/taggedTemplatesInDifferentScopes.types b/tests/baselines/reference/taggedTemplatesInDifferentScopes.types new file mode 100644 index 0000000000000..ea1faeacef460 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesInDifferentScopes.types @@ -0,0 +1,48 @@ +=== tests/cases/compiler/taggedTemplatesInDifferentScopes.ts === +export function tag(parts: TemplateStringsArray, ...values: any[]) { +>tag : (parts: TemplateStringsArray, ...values: any[]) => string +>parts : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>values : any[] + + return parts[0]; +>parts[0] : string +>parts : TemplateStringsArray +>0 : 0 +} +function foo() { +>foo : () => void + + tag `foo`; +>tag `foo` : string +>tag : (parts: TemplateStringsArray, ...values: any[]) => string +>`foo` : "foo" + + tag `foo2`; +>tag `foo2` : string +>tag : (parts: TemplateStringsArray, ...values: any[]) => string +>`foo2` : "foo2" +} + +function bar() { +>bar : () => void + + tag `bar`; +>tag `bar` : string +>tag : (parts: TemplateStringsArray, ...values: any[]) => string +>`bar` : "bar" + + tag `bar2`; +>tag `bar2` : string +>tag : (parts: TemplateStringsArray, ...values: any[]) => string +>`bar2` : "bar2" +} + +foo(); +>foo() : void +>foo : () => void + +bar(); +>bar() : void +>bar : () => void + diff --git a/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.js b/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.js index 737bdec55dc43..e8f5104ae74fd 100644 --- a/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.js +++ b/tests/baselines/reference/taggedTemplatesInModuleAndGlobal.js @@ -49,7 +49,7 @@ function id(x) { return x; } function templateObjectFactory() { - return id(_a || (_a = __makeTemplateObject(["hello world"], ["hello world"]))); + return id(templateObject_1 || (templateObject_1 = __makeTemplateObject(["hello world"], ["hello world"]))); } var result = templateObjectFactory() === templateObjectFactory(); -var _a; +var templateObject_1; From faa04a2402288654fddf36f08e969492bea9ef7c Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 13 Oct 2017 16:47:40 -0700 Subject: [PATCH 170/246] Update generated files (#19177) --- src/lib/dom.generated.d.ts | 12 +++++------- src/lib/webworker.generated.d.ts | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 420be2f0f5dc4..c7534fbd829bb 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -4833,6 +4833,7 @@ interface HTMLFormElement extends HTMLElement { * Fires when a FORM is about to be submitted. */ submit(): void; + reportValidity(): boolean; addEventListener(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; [name: string]: any; @@ -4961,9 +4962,6 @@ interface HTMLFrameSetElement extends HTMLElement { onafterprint: (this: HTMLFrameSetElement, ev: Event) => any; onbeforeprint: (this: HTMLFrameSetElement, ev: Event) => any; onbeforeunload: (this: HTMLFrameSetElement, ev: BeforeUnloadEvent) => any; - /** - * Fires when the object receives focus. - */ onhashchange: (this: HTMLFrameSetElement, ev: HashChangeEvent) => any; onmessage: (this: HTMLFrameSetElement, ev: MessageEvent) => any; onoffline: (this: HTMLFrameSetElement, ev: Event) => any; @@ -5108,7 +5106,6 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { * Sets or retrieves whether the user can resize the frame. */ noResize: boolean; - readonly sandbox: DOMSettableTokenList; /** * Sets or retrieves whether the frame can be scrolled. @@ -8205,6 +8202,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte readonly pointerEnabled: boolean; readonly serviceWorker: ServiceWorkerContainer; readonly webdriver: boolean; + readonly doNotTrack: string | null; readonly hardwareConcurrency: number; readonly languages: string[]; getGamepads(): Gamepad[]; @@ -13257,7 +13255,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window moveBy(x?: number, y?: number): void; moveTo(x?: number, y?: number): void; msWriteProfilerMark(profilerMarkName: string): void; - open(url?: string, target?: string, features?: string, replace?: boolean): Window; + open(url?: string, target?: string, features?: string, replace?: boolean): Window | null; postMessage(message: any, targetOrigin: string, transfer?: any[]): void; print(): void; prompt(message?: string, _default?: string): string | null; @@ -14006,7 +14004,7 @@ interface EcKeyAlgorithm extends KeyAlgorithm { typedCurve: string; } -interface EcKeyImportParams { +interface EcKeyImportParams extends Algorithm { namedCurve: string; } @@ -14657,7 +14655,7 @@ declare function matchMedia(mediaQuery: string): MediaQueryList; declare function moveBy(x?: number, y?: number): void; declare function moveTo(x?: number, y?: number): void; declare function msWriteProfilerMark(profilerMarkName: string): void; -declare function open(url?: string, target?: string, features?: string, replace?: boolean): Window; +declare function open(url?: string, target?: string, features?: string, replace?: boolean): Window | null; declare function postMessage(message: any, targetOrigin: string, transfer?: any[]): void; declare function print(): void; declare function prompt(message?: string, _default?: string): string | null; diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 821a7edd886fd..3416df4955a5a 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -1642,7 +1642,7 @@ interface EcKeyAlgorithm extends KeyAlgorithm { typedCurve: string; } -interface EcKeyImportParams { +interface EcKeyImportParams extends Algorithm { namedCurve: string; } From 07ff0fdb818623f6bc096dc140f4ae0015530ebf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Oct 2017 16:54:57 -0700 Subject: [PATCH 171/246] Properly handle mapped types with 'keyof any' --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9347329e624b2..f8f63bfe0f7b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5777,7 +5777,7 @@ namespace ts { for (const propertySymbol of getPropertiesOfType(modifiersType)) { addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol); } - if (getIndexInfoOfType(modifiersType, IndexKind.String)) { + if (modifiersType.flags & TypeFlags.Any || getIndexInfoOfType(modifiersType, IndexKind.String)) { addMemberForKeyType(stringType); } } @@ -8386,7 +8386,7 @@ namespace ts { } function isMappableType(type: Type) { - return type.flags & (TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess); + return type.flags & (TypeFlags.Any | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.Intersection | TypeFlags.IndexedAccess); } function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): AnonymousType { From 40cb9656f96fc6565a695e9c9ba6a4631da22f35 Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 14 Oct 2017 04:10:04 +0000 Subject: [PATCH 172/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17034 ++++++++-------- 1 file changed, 8556 insertions(+), 8478 deletions(-) diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index a895cdec898ae..603345e63b223 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8479 +1,8557 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - ou -. Por exemplo '{0}' ou '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - Promessa global.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' em vez disso.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + ou -. Por exemplo '{0}' ou '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + Promessa global.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' em vez disso.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From fa65bd20621536e6c7272e05dad9af5a7f36aeeb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 Oct 2017 09:53:51 -0700 Subject: [PATCH 173/246] Mapped type { [P in any]: T } should yield { [x: string]: T } --- 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 f8f63bfe0f7b5..9f4e3a60eb19d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5821,7 +5821,7 @@ namespace ts { prop.syntheticLiteralTypeOrigin = t as StringLiteralType; members.set(propName, prop); } - else if (t.flags & TypeFlags.String) { + else if (t.flags & (TypeFlags.Any | TypeFlags.String)) { stringIndexInfo = createIndexInfo(propType, templateReadonly); } } From ee0715a0736a0aa453b5020432790f07e0eb205f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 Oct 2017 11:13:40 -0700 Subject: [PATCH 174/246] Add tests --- .../types/mapped/mappedTypeWithAny.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/cases/conformance/types/mapped/mappedTypeWithAny.ts diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts new file mode 100644 index 0000000000000..f8b6f8a39b7d2 --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -0,0 +1,27 @@ +// @strict: true +// @declaration: true + +type Item = { value: string }; +type ItemMap = { [P in keyof T]: Item }; + +declare let x0: keyof any; +declare let x1: { [P in any]: Item }; +declare let x2: { [P in string]: Item }; +declare let x3: { [P in keyof any]: Item }; +declare let x4: ItemMap; + +// Repro from #19152 + +type Data = { + value: string; +} + +type StrictDataMap = { + [P in keyof T]: Data +} + +declare let z: StrictDataMap; +for (let id in z) { + let data = z[id]; + let x = data.notAValue; // Error +} From 8e47c18636da814117071a2640ccf87c5f16fcfd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 14 Oct 2017 11:13:52 -0700 Subject: [PATCH 175/246] Accept new baselines --- .../reference/mappedTypeWithAny.errors.txt | 31 ++++++++ .../baselines/reference/mappedTypeWithAny.js | 60 +++++++++++++++ .../reference/mappedTypeWithAny.symbols | 71 ++++++++++++++++++ .../reference/mappedTypeWithAny.types | 74 +++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 tests/baselines/reference/mappedTypeWithAny.errors.txt create mode 100644 tests/baselines/reference/mappedTypeWithAny.js create mode 100644 tests/baselines/reference/mappedTypeWithAny.symbols create mode 100644 tests/baselines/reference/mappedTypeWithAny.types diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt new file mode 100644 index 0000000000000..0ce53e5044d56 --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(23,16): error TS2339: Property 'notAValue' does not exist on type 'Data'. + + +==== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts (1 errors) ==== + type Item = { value: string }; + type ItemMap = { [P in keyof T]: Item }; + + declare let x0: keyof any; + declare let x1: { [P in any]: Item }; + declare let x2: { [P in string]: Item }; + declare let x3: { [P in keyof any]: Item }; + declare let x4: ItemMap; + + // Repro from #19152 + + type Data = { + value: string; + } + + type StrictDataMap = { + [P in keyof T]: Data + } + + declare let z: StrictDataMap; + for (let id in z) { + let data = z[id]; + let x = data.notAValue; // Error + ~~~~~~~~~ +!!! error TS2339: Property 'notAValue' does not exist on type 'Data'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js new file mode 100644 index 0000000000000..1e5c662310ca8 --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -0,0 +1,60 @@ +//// [mappedTypeWithAny.ts] +type Item = { value: string }; +type ItemMap = { [P in keyof T]: Item }; + +declare let x0: keyof any; +declare let x1: { [P in any]: Item }; +declare let x2: { [P in string]: Item }; +declare let x3: { [P in keyof any]: Item }; +declare let x4: ItemMap; + +// Repro from #19152 + +type Data = { + value: string; +} + +type StrictDataMap = { + [P in keyof T]: Data +} + +declare let z: StrictDataMap; +for (let id in z) { + let data = z[id]; + let x = data.notAValue; // Error +} + + +//// [mappedTypeWithAny.js] +"use strict"; +for (var id in z) { + var data = z[id]; + var x = data.notAValue; // Error +} + + +//// [mappedTypeWithAny.d.ts] +declare type Item = { + value: string; +}; +declare type ItemMap = { + [P in keyof T]: Item; +}; +declare let x0: keyof any; +declare let x1: { + [P in any]: Item; +}; +declare let x2: { + [P in string]: Item; +}; +declare let x3: { + [P in keyof any]: Item; +}; +declare let x4: ItemMap; +declare type Data = { + value: string; +}; +declare type StrictDataMap = { + [P in keyof T]: Data; +}; +declare let z: StrictDataMap; diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols new file mode 100644 index 0000000000000..2c204d4b1ef27 --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -0,0 +1,71 @@ +=== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts === +type Item = { value: string }; +>Item : Symbol(Item, Decl(mappedTypeWithAny.ts, 0, 0)) +>value : Symbol(value, Decl(mappedTypeWithAny.ts, 0, 13)) + +type ItemMap = { [P in keyof T]: Item }; +>ItemMap : Symbol(ItemMap, Decl(mappedTypeWithAny.ts, 0, 30)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 1, 13)) +>P : Symbol(P, Decl(mappedTypeWithAny.ts, 1, 21)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 1, 13)) +>Item : Symbol(Item, Decl(mappedTypeWithAny.ts, 0, 0)) + +declare let x0: keyof any; +>x0 : Symbol(x0, Decl(mappedTypeWithAny.ts, 3, 11)) + +declare let x1: { [P in any]: Item }; +>x1 : Symbol(x1, Decl(mappedTypeWithAny.ts, 4, 11)) +>P : Symbol(P, Decl(mappedTypeWithAny.ts, 4, 19)) +>Item : Symbol(Item, Decl(mappedTypeWithAny.ts, 0, 0)) + +declare let x2: { [P in string]: Item }; +>x2 : Symbol(x2, Decl(mappedTypeWithAny.ts, 5, 11)) +>P : Symbol(P, Decl(mappedTypeWithAny.ts, 5, 19)) +>Item : Symbol(Item, Decl(mappedTypeWithAny.ts, 0, 0)) + +declare let x3: { [P in keyof any]: Item }; +>x3 : Symbol(x3, Decl(mappedTypeWithAny.ts, 6, 11)) +>P : Symbol(P, Decl(mappedTypeWithAny.ts, 6, 19)) +>Item : Symbol(Item, Decl(mappedTypeWithAny.ts, 0, 0)) + +declare let x4: ItemMap; +>x4 : Symbol(x4, Decl(mappedTypeWithAny.ts, 7, 11)) +>ItemMap : Symbol(ItemMap, Decl(mappedTypeWithAny.ts, 0, 30)) + +// Repro from #19152 + +type Data = { +>Data : Symbol(Data, Decl(mappedTypeWithAny.ts, 7, 29)) + + value: string; +>value : Symbol(value, Decl(mappedTypeWithAny.ts, 11, 13)) +} + +type StrictDataMap = { +>StrictDataMap : Symbol(StrictDataMap, Decl(mappedTypeWithAny.ts, 13, 1)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 15, 19)) + + [P in keyof T]: Data +>P : Symbol(P, Decl(mappedTypeWithAny.ts, 16, 3)) +>T : Symbol(T, Decl(mappedTypeWithAny.ts, 15, 19)) +>Data : Symbol(Data, Decl(mappedTypeWithAny.ts, 7, 29)) +} + +declare let z: StrictDataMap; +>z : Symbol(z, Decl(mappedTypeWithAny.ts, 19, 11)) +>StrictDataMap : Symbol(StrictDataMap, Decl(mappedTypeWithAny.ts, 13, 1)) + +for (let id in z) { +>id : Symbol(id, Decl(mappedTypeWithAny.ts, 20, 8)) +>z : Symbol(z, Decl(mappedTypeWithAny.ts, 19, 11)) + + let data = z[id]; +>data : Symbol(data, Decl(mappedTypeWithAny.ts, 21, 5)) +>z : Symbol(z, Decl(mappedTypeWithAny.ts, 19, 11)) +>id : Symbol(id, Decl(mappedTypeWithAny.ts, 20, 8)) + + let x = data.notAValue; // Error +>x : Symbol(x, Decl(mappedTypeWithAny.ts, 22, 5)) +>data : Symbol(data, Decl(mappedTypeWithAny.ts, 21, 5)) +} + diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types new file mode 100644 index 0000000000000..36fad9140cc35 --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -0,0 +1,74 @@ +=== tests/cases/conformance/types/mapped/mappedTypeWithAny.ts === +type Item = { value: string }; +>Item : Item +>value : string + +type ItemMap = { [P in keyof T]: Item }; +>ItemMap : ItemMap +>T : T +>P : P +>T : T +>Item : Item + +declare let x0: keyof any; +>x0 : string + +declare let x1: { [P in any]: Item }; +>x1 : { [x: string]: Item; } +>P : P +>Item : Item + +declare let x2: { [P in string]: Item }; +>x2 : { [x: string]: Item; } +>P : P +>Item : Item + +declare let x3: { [P in keyof any]: Item }; +>x3 : { [x: string]: Item; } +>P : P +>Item : Item + +declare let x4: ItemMap; +>x4 : ItemMap +>ItemMap : ItemMap + +// Repro from #19152 + +type Data = { +>Data : Data + + value: string; +>value : string +} + +type StrictDataMap = { +>StrictDataMap : StrictDataMap +>T : T + + [P in keyof T]: Data +>P : P +>T : T +>Data : Data +} + +declare let z: StrictDataMap; +>z : StrictDataMap +>StrictDataMap : StrictDataMap + +for (let id in z) { +>id : string +>z : StrictDataMap + + let data = z[id]; +>data : Data +>z[id] : Data +>z : StrictDataMap +>id : string + + let x = data.notAValue; // Error +>x : any +>data.notAValue : any +>data : Data +>notAValue : any +} + From 30c51ed3249a1701c5d1faeb169717ff009d6ad5 Mon Sep 17 00:00:00 2001 From: kingwl <805037171@163.com> Date: Mon, 16 Oct 2017 10:39:55 +0800 Subject: [PATCH 176/246] fix super call from class that has no basetype but with same symbol interface (#19068) --- src/compiler/checker.ts | 8 +++++--- ...aseTypeButWithSameSymbolInterface.errors.txt | 14 ++++++++++++++ ...atHasNoBaseTypeButWithSameSymbolInterface.js | 17 +++++++++++++++++ ...NoBaseTypeButWithSameSymbolInterface.symbols | 13 +++++++++++++ ...asNoBaseTypeButWithSameSymbolInterface.types | 15 +++++++++++++++ ...atHasNoBaseTypeButWithSameSymbolInterface.ts | 7 +++++++ 6 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types create mode 100644 tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3208615755227..bd97a49fa4547 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13043,12 +13043,14 @@ namespace ts { // at this point the only legal case for parent is ClassLikeDeclaration const classLikeDeclaration = container.parent; + if (!getClassExtendsHeritageClauseElement(classLikeDeclaration)) { + error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); + return unknownType; + } + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)); const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { - if (!getClassExtendsHeritageClauseElement(classLikeDeclaration)) { - error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); - } return unknownType; } diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt new file mode 100644 index 0000000000000..44963f797ea90 --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts(5,9): error TS2335: 'super' can only be referenced in a derived class. + + +==== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts (1 errors) ==== + interface Foo extends Array {} + + class Foo { + constructor() { + super(); // error + ~~~~~ +!!! error TS2335: 'super' can only be referenced in a derived class. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js new file mode 100644 index 0000000000000..e933ec9daa2c9 --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js @@ -0,0 +1,17 @@ +//// [superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts] +interface Foo extends Array {} + +class Foo { + constructor() { + super(); // error + } +} + + +//// [superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js] +var Foo = /** @class */ (function () { + function Foo() { + _this = _super.call(this) || this; // error + } + return Foo; +}()); diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols new file mode 100644 index 0000000000000..a8ff0f10b4fcb --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts === +interface Foo extends Array {} +>Foo : Symbol(Foo, Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 0), Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 38)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +class Foo { +>Foo : Symbol(Foo, Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 0), Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 38)) + + constructor() { + super(); // error + } +} + diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types new file mode 100644 index 0000000000000..f2e5ad1706388 --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts === +interface Foo extends Array {} +>Foo : Foo +>Array : T[] + +class Foo { +>Foo : Foo + + constructor() { + super(); // error +>super() : void +>super : any + } +} + diff --git a/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts b/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts new file mode 100644 index 0000000000000..3afd827594129 --- /dev/null +++ b/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts @@ -0,0 +1,7 @@ +interface Foo extends Array {} + +class Foo { + constructor() { + super(); // error + } +} From 9306543431bb4c97dff8b6f193c02becd12c6bfb Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 16 Oct 2017 16:10:13 +0000 Subject: [PATCH 177/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17108 +++++++-------- .../diagnosticMessages.generated.json.lcl | 17120 ++++++++-------- .../diagnosticMessages.generated.json.lcl | 17105 +++++++-------- 3 files changed, 25782 insertions(+), 25551 deletions(-) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index bed8ce927b815..16310396458a1 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8516 +1,8594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - 或 <語言>-<國家/地區>。例如 '{0}' 或 '{1}'。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - 類型。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()'。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + 或 <語言>-<國家/地區>。例如 '{0}' 或 '{1}'。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + 類型。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()'。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index bbf200457e9a0..a2963d878f6c4 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8525 +1,8597 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - o -. Por ejemplo, '{0}' o '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - global.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()" en su lugar.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + o -. Por ejemplo, '{0}' o '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + global.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()" en su lugar.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index a7248df81afab..de906e32915dd 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8513 +1,8594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - または - の形式で指定する必要があります (例: '{0}'、'{1}')。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - 型である必要があります。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' を使用してください。]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + または - の形式で指定する必要があります (例: '{0}'、'{1}')。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + 型である必要があります。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' を使用してください。]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 3c27e782da3b2242c42eb0e883cb0a58444b3dcf Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 11:22:49 -0700 Subject: [PATCH 178/246] Add getCompilerOptions method to project Fixes #19218 --- src/server/project.ts | 4 ++++ tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/src/server/project.ts b/src/server/project.ts index 7653fbf93cfa4..ca6e82ec4be1b 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -246,6 +246,10 @@ namespace ts.server { return this.compilerOptions; } + getCompilerOptions() { + return this.compilerOptions; + } + getNewLine() { return this.directoryStructureHost.newLine; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 151c948602de4..e983ac73b1551 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7109,6 +7109,7 @@ declare namespace ts.server { getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap; static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; getCompilationSettings(): CompilerOptions; + getCompilerOptions(): CompilerOptions; getNewLine(): string; getProjectVersion(): string; getScriptFileNames(): string[]; From bac30fc1a2ab3d99c5f22891da8110d47c16e242 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 16 Oct 2017 11:41:35 -0700 Subject: [PATCH 179/246] In convertFunctionToEs6Class.ts, share code for getting symbol (#19160) --- .../refactors/convertFunctionToEs6Class.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index e9f229fa0d78f..f5951bd26e408 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -17,16 +17,16 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const start = context.startPosition; - const node = getTokenAtPosition(context.file, start, /*includeJsDocComment*/ false); - const checker = context.program.getTypeChecker(); - let symbol = checker.getSymbolAtLocation(node); + let symbol = getConstructorSymbol(context); + if (!symbol) { + return undefined; + } - if (symbol && isDeclarationOfFunctionOrClassExpression(symbol)) { + if (isDeclarationOfFunctionOrClassExpression(symbol)) { symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol; } - if (symbol && (symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { + if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { return [ { name: convertFunctionToES6Class.name, @@ -48,11 +48,8 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const start = context.startPosition; - const sourceFile = context.file; - const checker = context.program.getTypeChecker(); - const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); - const ctorSymbol = checker.getSymbolAtLocation(token); + const { file: sourceFile } = context; + const ctorSymbol = getConstructorSymbol(context); const newLine = context.rulesProvider.getFormatOptions().newLineCharacter; const deletedNodes: Node[] = []; @@ -269,4 +266,10 @@ namespace ts.refactor.convertFunctionToES6Class { return filter(source.modifiers, modifier => modifier.kind === kind); } } -} + + function getConstructorSymbol({ startPosition, file, program }: RefactorContext): Symbol { + const checker = program.getTypeChecker(); + const token = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); + return checker.getSymbolAtLocation(token); + } +} \ No newline at end of file From 40222d1a77a32ae412df8bda49f7ff20cfd8c3ba Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 16 Oct 2017 12:57:23 -0700 Subject: [PATCH 180/246] Fix for-in emit under systemjs (#19223) --- src/compiler/transformers/module/system.ts | 5 ++++- .../reference/systemJsForInNoException.js | 19 ++++++++++++++++++ .../systemJsForInNoException.symbols | 16 +++++++++++++++ .../reference/systemJsForInNoException.types | 20 +++++++++++++++++++ .../compiler/systemJsForInNoException.ts | 5 +++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/systemJsForInNoException.js create mode 100644 tests/baselines/reference/systemJsForInNoException.symbols create mode 100644 tests/baselines/reference/systemJsForInNoException.types create mode 100644 tests/cases/compiler/systemJsForInNoException.ts diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index ed943eb90ce79..d674546efb902 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -826,7 +826,7 @@ namespace ts { /*needsValue*/ false, createAssignment ) - : createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression)); + : node.initializer ? createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression)) : node.name; } /** @@ -1296,6 +1296,9 @@ namespace ts { let expressions: Expression[]; for (const variable of node.declarations) { expressions = append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); + if (!variable.initializer) { + hoistBindingElement(variable); + } } return expressions ? inlineExpressions(expressions) : createOmittedExpression(); diff --git a/tests/baselines/reference/systemJsForInNoException.js b/tests/baselines/reference/systemJsForInNoException.js new file mode 100644 index 0000000000000..2ac31e18416cc --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.js @@ -0,0 +1,19 @@ +//// [systemJsForInNoException.ts] +export const obj = { a: 1 }; +for (var key in obj) + console.log(obj[key]); + +//// [systemJsForInNoException.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var obj, key; + return { + setters: [], + execute: function () { + exports_1("obj", obj = { a: 1 }); + for (key in obj) + console.log(obj[key]); + } + }; +}); diff --git a/tests/baselines/reference/systemJsForInNoException.symbols b/tests/baselines/reference/systemJsForInNoException.symbols new file mode 100644 index 0000000000000..4d4d2e0206c86 --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/systemJsForInNoException.ts === +export const obj = { a: 1 }; +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) +>a : Symbol(a, Decl(systemJsForInNoException.ts, 0, 20)) + +for (var key in obj) +>key : Symbol(key, Decl(systemJsForInNoException.ts, 1, 8)) +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) + + console.log(obj[key]); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) +>key : Symbol(key, Decl(systemJsForInNoException.ts, 1, 8)) + diff --git a/tests/baselines/reference/systemJsForInNoException.types b/tests/baselines/reference/systemJsForInNoException.types new file mode 100644 index 0000000000000..6d9dbbb6e7b48 --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/systemJsForInNoException.ts === +export const obj = { a: 1 }; +>obj : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +for (var key in obj) +>key : string +>obj : { a: number; } + + console.log(obj[key]); +>console.log(obj[key]) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj[key] : any +>obj : { a: number; } +>key : string + diff --git a/tests/cases/compiler/systemJsForInNoException.ts b/tests/cases/compiler/systemJsForInNoException.ts new file mode 100644 index 0000000000000..e35c3aa24a353 --- /dev/null +++ b/tests/cases/compiler/systemJsForInNoException.ts @@ -0,0 +1,5 @@ +// @module: system +// @lib: es6,dom +export const obj = { a: 1 }; +for (var key in obj) + console.log(obj[key]); \ No newline at end of file From 2cb0403e2d6165e1eb3731173164f307f556ef0a Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 16 Oct 2017 13:02:15 -0700 Subject: [PATCH 181/246] Support 'package.json' not in package root (#19133) * Support 'package.json' not in package root * Test "foo/@bar" * More tests, and don't use "types" from the root package.json if not loading the root module --- src/compiler/moduleNameResolver.ts | 40 +++++++++++++------ ...Resolution_packageJson_notAtPackageRoot.js | 20 ++++++++++ ...ution_packageJson_notAtPackageRoot.symbols | 8 ++++ ...on_packageJson_notAtPackageRoot.trace.json | 14 +++++++ ...olution_packageJson_notAtPackageRoot.types | 8 ++++ ...Json_notAtPackageRoot_fakeScopedPackage.js | 20 ++++++++++ ...notAtPackageRoot_fakeScopedPackage.symbols | 8 ++++ ...AtPackageRoot_fakeScopedPackage.trace.json | 14 +++++++ ...n_notAtPackageRoot_fakeScopedPackage.types | 8 ++++ ...Resolution_packageJson_yesAtPackageRoot.js | 18 +++++++++ ...ution_packageJson_yesAtPackageRoot.symbols | 4 ++ ...on_packageJson_yesAtPackageRoot.trace.json | 22 ++++++++++ ...olution_packageJson_yesAtPackageRoot.types | 4 ++ ...Json_yesAtPackageRoot_fakeScopedPackage.js | 20 ++++++++++ ...yesAtPackageRoot_fakeScopedPackage.symbols | 4 ++ ...AtPackageRoot_fakeScopedPackage.trace.json | 22 ++++++++++ ...n_yesAtPackageRoot_fakeScopedPackage.types | 4 ++ ...Resolution_packageJson_notAtPackageRoot.ts | 16 ++++++++ ...Json_notAtPackageRoot_fakeScopedPackage.ts | 16 ++++++++ ...Resolution_packageJson_yesAtPackageRoot.ts | 14 +++++++ ...Json_yesAtPackageRoot_fakeScopedPackage.ts | 16 ++++++++ 21 files changed, 288 insertions(+), 12 deletions(-) create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types create mode 100644 tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index ac83dd4131195..08178d3d16aad 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -77,16 +77,20 @@ namespace ts { traceEnabled: boolean; } - interface PackageJson { - name?: string; - version?: string; + /** Just the fields that we use for module resolution. */ + interface PackageJsonPathFields { typings?: string; types?: string; main?: string; } + interface PackageJson extends PackageJsonPathFields { + name?: string; + version?: string; + } + /** Reads from "main" or "types"/"typings" depending on `extensions`. */ - function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState): string | undefined { + function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJsonPathFields, baseDirectory: string, state: ModuleResolutionState): string | undefined { return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main"); function tryReadFromField(fieldName: "typings" | "types" | "main"): string | undefined { @@ -886,7 +890,7 @@ namespace ts { return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, packageJsonContent)); } - function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJson | undefined): PathAndExtension | undefined { + function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined): PathAndExtension | undefined { const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, extensions, candidate, failedLookupLocations, state); if (fromPackageJson) { return fromPackageJson; @@ -901,7 +905,7 @@ namespace ts { failedLookupLocations: Push, onlyRecordFailures: boolean, { host, traceEnabled }: ModuleResolutionState, - ): { packageJsonContent: PackageJson | undefined, packageId: PackageId | undefined } { + ): { found: boolean, packageJsonContent: PackageJsonPathFields | undefined, packageId: PackageId | undefined } { const directoryExists = !onlyRecordFailures && directoryProbablyExists(nodeModuleDirectory, host); const packageJsonPath = pathToPackageJson(nodeModuleDirectory); if (directoryExists && host.fileExists(packageJsonPath)) { @@ -912,7 +916,7 @@ namespace ts { const packageId: PackageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" ? { name: packageJsonContent.name, subModuleName, version: packageJsonContent.version } : undefined; - return { packageJsonContent, packageId }; + return { found: true, packageJsonContent, packageId }; } else { if (directoryExists && traceEnabled) { @@ -920,11 +924,11 @@ namespace ts { } // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocations.push(packageJsonPath); - return { packageJsonContent: undefined, packageId: undefined }; + return { found: false, packageJsonContent: undefined, packageId: undefined }; } } - function loadModuleFromPackageJson(jsonContent: PackageJson, extensions: Extensions, candidate: string, failedLookupLocations: Push, state: ModuleResolutionState): PathAndExtension | undefined { + function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, extensions: Extensions, candidate: string, failedLookupLocations: Push, state: ModuleResolutionState): PathAndExtension | undefined { const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, jsonContent, candidate, state); if (!file) { return undefined; @@ -976,10 +980,22 @@ namespace ts { } function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - const { packageName, rest } = getPackageName(moduleName); - const packageRootPath = combinePaths(nodeModulesFolder, packageName); - const { packageJsonContent, packageId } = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state); const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); + // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. + let packageJsonContent: PackageJsonPathFields | undefined; + let packageId: PackageId | undefined; + const packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, /*onlyRecordFailures*/ !nodeModulesFolderExists, state); + if (packageInfo.found) { + ({ packageJsonContent, packageId } = packageInfo); + } + else { + const { packageName, rest } = getPackageName(moduleName); + if (rest !== "") { // If "rest" is empty, we just did this search above. + const packageRootPath = combinePaths(nodeModulesFolder, packageName); + // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId. + packageId = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state).packageId; + } + } const pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js new file mode 100644 index 0000000000000..941774f4d3520 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts] //// + +//// [package.json] +// Loads from a "fake" nested package.json, not from the one at the root. + +{ "types": "types.d.ts" } + +//// [package.json] +{} + +//// [types.d.ts] +export const x: number; + +//// [a.ts] +import { x } from "foo/bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols new file mode 100644 index 0000000000000..57aaa9a96ef5d --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +=== /node_modules/foo/bar/types.d.ts === +export const x: number; +>x : Symbol(x, Decl(types.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json new file mode 100644 index 0000000000000..bf5f0b0bbeff6 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json @@ -0,0 +1,14 @@ +[ + "======== Resolving module 'foo/bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "Found 'package.json' at '/node_modules/foo/bar/package.json'.", + "File '/node_modules/foo/bar.ts' does not exist.", + "File '/node_modules/foo/bar.tsx' does not exist.", + "File '/node_modules/foo/bar.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/bar/types.d.ts'.", + "File '/node_modules/foo/bar/types.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/bar/types.d.ts', result '/node_modules/foo/bar/types.d.ts'.", + "======== Module name 'foo/bar' was successfully resolved to '/node_modules/foo/bar/types.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types new file mode 100644 index 0000000000000..68a1585d768ac --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : number + +=== /node_modules/foo/bar/types.d.ts === +export const x: number; +>x : number + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js new file mode 100644 index 0000000000000..4539828924157 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts] //// + +//// [package.json] +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +{ "types": "types.d.ts" } + +//// [package.json] +{} + +//// [types.d.ts] +export const x: number; + +//// [a.ts] +import { x } from "foo/@bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols new file mode 100644 index 0000000000000..de21d67b6295f --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +=== /node_modules/foo/@bar/types.d.ts === +export const x: number; +>x : Symbol(x, Decl(types.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json new file mode 100644 index 0000000000000..72d413d0b2c3a --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json @@ -0,0 +1,14 @@ +[ + "======== Resolving module 'foo/@bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", + "Found 'package.json' at '/node_modules/foo/@bar/package.json'.", + "File '/node_modules/foo/@bar.ts' does not exist.", + "File '/node_modules/foo/@bar.tsx' does not exist.", + "File '/node_modules/foo/@bar.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/@bar/types.d.ts'.", + "File '/node_modules/foo/@bar/types.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/@bar/types.d.ts', result '/node_modules/foo/@bar/types.d.ts'.", + "======== Module name 'foo/@bar' was successfully resolved to '/node_modules/foo/@bar/types.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types new file mode 100644 index 0000000000000..6d8894ebce1ab --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : number + +=== /node_modules/foo/@bar/types.d.ts === +export const x: number; +>x : number + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js new file mode 100644 index 0000000000000..ed006b0e62dcd --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts] //// + +//// [index.js] +not read + +//// [package.json] +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +//// [types.d.ts] +export const x = 0; + +//// [a.ts] +import { x } from "foo/bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols new file mode 100644 index 0000000000000..c037bb343b046 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json new file mode 100644 index 0000000000000..3a87769891b61 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json @@ -0,0 +1,22 @@ +[ + "======== Resolving module 'foo/bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "File '/node_modules/foo/bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/bar.ts' does not exist.", + "File '/node_modules/foo/bar.tsx' does not exist.", + "File '/node_modules/foo/bar.d.ts' does not exist.", + "File '/node_modules/foo/bar/index.ts' does not exist.", + "File '/node_modules/foo/bar/index.tsx' does not exist.", + "File '/node_modules/foo/bar/index.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'JavaScript'.", + "File '/node_modules/foo/bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/bar.js' does not exist.", + "File '/node_modules/foo/bar.jsx' does not exist.", + "File '/node_modules/foo/bar/index.js' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/bar/index.js', result '/node_modules/foo/bar/index.js'.", + "======== Module name 'foo/bar' was successfully resolved to '/node_modules/foo/bar/index.js'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types new file mode 100644 index 0000000000000..460aa4b8f05c9 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : any + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js new file mode 100644 index 0000000000000..129feb6060f24 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts] //// + +//// [index.js] +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +not read + +//// [package.json] +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +//// [types.d.ts] +export const x = 0; + +//// [a.ts] +import { x } from "foo/@bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols new file mode 100644 index 0000000000000..d1c3839b87b62 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json new file mode 100644 index 0000000000000..c28189a1f7d22 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json @@ -0,0 +1,22 @@ +[ + "======== Resolving module 'foo/@bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", + "File '/node_modules/foo/@bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/@bar.ts' does not exist.", + "File '/node_modules/foo/@bar.tsx' does not exist.", + "File '/node_modules/foo/@bar.d.ts' does not exist.", + "File '/node_modules/foo/@bar/index.ts' does not exist.", + "File '/node_modules/foo/@bar/index.tsx' does not exist.", + "File '/node_modules/foo/@bar/index.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'JavaScript'.", + "File '/node_modules/foo/@bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/@bar.js' does not exist.", + "File '/node_modules/foo/@bar.jsx' does not exist.", + "File '/node_modules/foo/@bar/index.js' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/@bar/index.js', result '/node_modules/foo/@bar/index.js'.", + "======== Module name 'foo/@bar' was successfully resolved to '/node_modules/foo/@bar/index.js'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types new file mode 100644 index 0000000000000..47b12eea7a172 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : any + diff --git a/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts new file mode 100644 index 0000000000000..a93ea832b7351 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Loads from a "fake" nested package.json, not from the one at the root. + +// @Filename: /node_modules/foo/bar/package.json +{ "types": "types.d.ts" } + +// @Filename: /node_modules/foo/package.json +{} + +// @Filename: /node_modules/foo/bar/types.d.ts +export const x: number; + +// @Filename: /a.ts +import { x } from "foo/bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts new file mode 100644 index 0000000000000..55e3963357f95 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +// @Filename: /node_modules/foo/@bar/package.json +{ "types": "types.d.ts" } + +// @Filename: /node_modules/foo/package.json +{} + +// @Filename: /node_modules/foo/@bar/types.d.ts +export const x: number; + +// @Filename: /a.ts +import { x } from "foo/@bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts new file mode 100644 index 0000000000000..64e46c4e71004 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts @@ -0,0 +1,14 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// @Filename: /node_modules/foo/bar/index.js +not read + +// @Filename: /node_modules/foo/package.json +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +// @Filename: /node_modules/foo/types.d.ts +export const x = 0; + +// @Filename: /a.ts +import { x } from "foo/bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts new file mode 100644 index 0000000000000..9b9f35b41e772 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +// @Filename: /node_modules/foo/@bar/index.js +not read + +// @Filename: /node_modules/foo/package.json +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +// @Filename: /node_modules/foo/types.d.ts +export const x = 0; + +// @Filename: /a.ts +import { x } from "foo/@bar"; From 734bda833c2236ab2360e798b9465425e80f62ab Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 13:06:15 -0700 Subject: [PATCH 182/246] Add comments about why we need two methods that return compilerOptions --- src/server/project.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/project.ts b/src/server/project.ts index ca6e82ec4be1b..9c3fab63d2306 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -242,12 +242,14 @@ namespace ts.server { this.markAsDirty(); } + // Method of LanguageServiceHost getCompilationSettings() { return this.compilerOptions; } + // Method to support public API getCompilerOptions() { - return this.compilerOptions; + return this.getCompilationSettings(); } getNewLine() { From aea7e9a7a812d02bf36fd0f36192fb81d8433afc Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 16 Oct 2017 14:17:55 -0700 Subject: [PATCH 183/246] Fix instantiated generic mixin declaration emit (#19144) * Fix #18545, dont use declared type of class expression * Accept API Baselines * Add thus far unused flag from node builder * Accept baseline update --- src/compiler/checker.ts | 2 +- .../declarationNoDanglingGenerics.js | 125 ++++++++++++++++++ .../declarationNoDanglingGenerics.symbols | 82 ++++++++++++ .../declarationNoDanglingGenerics.types | 98 ++++++++++++++ .../compiler/declarationNoDanglingGenerics.ts | 33 +++++ 5 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.js create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.symbols create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.types create mode 100644 tests/cases/compiler/declarationNoDanglingGenerics.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3208615755227..8f8be4a10ef6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3398,7 +3398,7 @@ namespace ts { else if (flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) { - writeAnonymousType(getDeclaredTypeOfClassOrInterface(type.symbol), flags); + writeAnonymousType(type, flags); } else { // Write the type reference in the format f.g.C where A and B are type arguments diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.js b/tests/baselines/reference/declarationNoDanglingGenerics.js new file mode 100644 index 0000000000000..9045be6827bdb --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.js @@ -0,0 +1,125 @@ +//// [declarationNoDanglingGenerics.ts] +const kindCache: { [kind: string]: boolean } = {}; + +function register(kind: string): void | never { + if (kindCache[kind]) { + throw new Error(`Class with kind "${kind}" is already registered.`); + } + kindCache[kind] = true; +} + +function ClassFactory(kind: TKind) { + register(kind); + + return class { + static readonly THE_KIND: TKind = kind; + readonly kind: TKind = kind; + }; +} + +class Kinds { + static readonly A = "A"; + static readonly B = "B"; + static readonly C = "C"; +} + +export class AKind extends ClassFactory(Kinds.A) { +} + +export class BKind extends ClassFactory(Kinds.B) { +} + +export class CKind extends ClassFactory(Kinds.C) { +} + +//// [declarationNoDanglingGenerics.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var kindCache = {}; +function register(kind) { + if (kindCache[kind]) { + throw new Error("Class with kind \"" + kind + "\" is already registered."); + } + kindCache[kind] = true; +} +function ClassFactory(kind) { + register(kind); + return _a = /** @class */ (function () { + function class_1() { + this.kind = kind; + } + return class_1; + }()), + _a.THE_KIND = kind, + _a; + var _a; +} +var Kinds = /** @class */ (function () { + function Kinds() { + } + Kinds.A = "A"; + Kinds.B = "B"; + Kinds.C = "C"; + return Kinds; +}()); +var AKind = /** @class */ (function (_super) { + __extends(AKind, _super); + function AKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return AKind; +}(ClassFactory(Kinds.A))); +exports.AKind = AKind; +var BKind = /** @class */ (function (_super) { + __extends(BKind, _super); + function BKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return BKind; +}(ClassFactory(Kinds.B))); +exports.BKind = BKind; +var CKind = /** @class */ (function (_super) { + __extends(CKind, _super); + function CKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return CKind; +}(ClassFactory(Kinds.C))); +exports.CKind = CKind; + + +//// [declarationNoDanglingGenerics.d.ts] +declare const AKind_base: { + new (): { + readonly kind: "A"; + }; + readonly THE_KIND: "A"; +}; +export declare class AKind extends AKind_base { +} +declare const BKind_base: { + new (): { + readonly kind: "B"; + }; + readonly THE_KIND: "B"; +}; +export declare class BKind extends BKind_base { +} +declare const CKind_base: { + new (): { + readonly kind: "C"; + }; + readonly THE_KIND: "C"; +}; +export declare class CKind extends CKind_base { +} diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.symbols b/tests/baselines/reference/declarationNoDanglingGenerics.symbols new file mode 100644 index 0000000000000..512bf95d4bbc3 --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.symbols @@ -0,0 +1,82 @@ +=== tests/cases/compiler/declarationNoDanglingGenerics.ts === +const kindCache: { [kind: string]: boolean } = {}; +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 0, 20)) + +function register(kind: string): void | never { +>register : Symbol(register, Decl(declarationNoDanglingGenerics.ts, 0, 50)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + + if (kindCache[kind]) { +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + + throw new Error(`Class with kind "${kind}" is already registered.`); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + } + kindCache[kind] = true; +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) +} + +function ClassFactory(kind: TKind) { +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) + + register(kind); +>register : Symbol(register, Decl(declarationNoDanglingGenerics.ts, 0, 50)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + return class { + static readonly THE_KIND: TKind = kind; +>THE_KIND : Symbol((Anonymous class).THE_KIND, Decl(declarationNoDanglingGenerics.ts, 12, 16)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + readonly kind: TKind = kind; +>kind : Symbol((Anonymous class).kind, Decl(declarationNoDanglingGenerics.ts, 13, 43)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + }; +} + +class Kinds { +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) + + static readonly A = "A"; +>A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) + + static readonly B = "B"; +>B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) + + static readonly C = "C"; +>C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +} + +export class AKind extends ClassFactory(Kinds.A) { +>AKind : Symbol(AKind, Decl(declarationNoDanglingGenerics.ts, 22, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) +} + +export class BKind extends ClassFactory(Kinds.B) { +>BKind : Symbol(BKind, Decl(declarationNoDanglingGenerics.ts, 25, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) +} + +export class CKind extends ClassFactory(Kinds.C) { +>CKind : Symbol(CKind, Decl(declarationNoDanglingGenerics.ts, 28, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +} diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.types b/tests/baselines/reference/declarationNoDanglingGenerics.types new file mode 100644 index 0000000000000..c650839be16c2 --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.types @@ -0,0 +1,98 @@ +=== tests/cases/compiler/declarationNoDanglingGenerics.ts === +const kindCache: { [kind: string]: boolean } = {}; +>kindCache : { [kind: string]: boolean; } +>kind : string +>{} : {} + +function register(kind: string): void | never { +>register : (kind: string) => void +>kind : string + + if (kindCache[kind]) { +>kindCache[kind] : boolean +>kindCache : { [kind: string]: boolean; } +>kind : string + + throw new Error(`Class with kind "${kind}" is already registered.`); +>new Error(`Class with kind "${kind}" is already registered.`) : Error +>Error : ErrorConstructor +>`Class with kind "${kind}" is already registered.` : string +>kind : string + } + kindCache[kind] = true; +>kindCache[kind] = true : true +>kindCache[kind] : boolean +>kindCache : { [kind: string]: boolean; } +>kind : string +>true : true +} + +function ClassFactory(kind: TKind) { +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>TKind : TKind +>kind : TKind +>TKind : TKind + + register(kind); +>register(kind) : void +>register : (kind: string) => void +>kind : TKind + + return class { +>class { static readonly THE_KIND: TKind = kind; readonly kind: TKind = kind; } : typeof (Anonymous class) + + static readonly THE_KIND: TKind = kind; +>THE_KIND : TKind +>TKind : TKind +>kind : TKind + + readonly kind: TKind = kind; +>kind : TKind +>TKind : TKind +>kind : TKind + + }; +} + +class Kinds { +>Kinds : Kinds + + static readonly A = "A"; +>A : "A" +>"A" : "A" + + static readonly B = "B"; +>B : "B" +>"B" : "B" + + static readonly C = "C"; +>C : "C" +>"C" : "C" +} + +export class AKind extends ClassFactory(Kinds.A) { +>AKind : AKind +>ClassFactory(Kinds.A) : ClassFactory<"A">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.A : "A" +>Kinds : typeof Kinds +>A : "A" +} + +export class BKind extends ClassFactory(Kinds.B) { +>BKind : BKind +>ClassFactory(Kinds.B) : ClassFactory<"B">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.B : "B" +>Kinds : typeof Kinds +>B : "B" +} + +export class CKind extends ClassFactory(Kinds.C) { +>CKind : CKind +>ClassFactory(Kinds.C) : ClassFactory<"C">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.C : "C" +>Kinds : typeof Kinds +>C : "C" +} diff --git a/tests/cases/compiler/declarationNoDanglingGenerics.ts b/tests/cases/compiler/declarationNoDanglingGenerics.ts new file mode 100644 index 0000000000000..baedcc8a74ee9 --- /dev/null +++ b/tests/cases/compiler/declarationNoDanglingGenerics.ts @@ -0,0 +1,33 @@ +// @declaration: true +const kindCache: { [kind: string]: boolean } = {}; + +function register(kind: string): void | never { + if (kindCache[kind]) { + throw new Error(`Class with kind "${kind}" is already registered.`); + } + kindCache[kind] = true; +} + +function ClassFactory(kind: TKind) { + register(kind); + + return class { + static readonly THE_KIND: TKind = kind; + readonly kind: TKind = kind; + }; +} + +class Kinds { + static readonly A = "A"; + static readonly B = "B"; + static readonly C = "C"; +} + +export class AKind extends ClassFactory(Kinds.A) { +} + +export class BKind extends ClassFactory(Kinds.B) { +} + +export class CKind extends ClassFactory(Kinds.C) { +} \ No newline at end of file From 9563246993fdc4d323db60179a8bfd84a943cd70 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 16 Oct 2017 14:26:16 -0700 Subject: [PATCH 184/246] Do not reduce subtypes of awaited union type --- src/compiler/checker.ts | 2 +- .../baselines/reference/awaitUnionPromise.js | 89 +++++++++++++++++++ .../reference/awaitUnionPromise.symbols | 67 ++++++++++++++ .../reference/awaitUnionPromise.types | 76 ++++++++++++++++ tests/cases/compiler/awaitUnionPromise.ts | 19 ++++ 5 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/awaitUnionPromise.js create mode 100644 tests/baselines/reference/awaitUnionPromise.symbols create mode 100644 tests/baselines/reference/awaitUnionPromise.types create mode 100644 tests/cases/compiler/awaitUnionPromise.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9347329e624b2..9934793ace56e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19680,7 +19680,7 @@ namespace ts { return undefined; } - return typeAsAwaitable.awaitedTypeOfType = getUnionType(types, /*subtypeReduction*/ true); + return typeAsAwaitable.awaitedTypeOfType = getUnionType(types); } const promisedType = getPromisedTypeOfPromise(type); diff --git a/tests/baselines/reference/awaitUnionPromise.js b/tests/baselines/reference/awaitUnionPromise.js new file mode 100644 index 0000000000000..df4c937fc6341 --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.js @@ -0,0 +1,89 @@ +//// [awaitUnionPromise.ts] +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; + +interface IAsyncEnumerator { + next1(): Promise; + next2(): Promise | Promise; + next3(): Promise; + next4(): Promise; +} + +async function main() { + const x: IAsyncEnumerator = null; + let a = await x.next1(); + let b = await x.next2(); + let c = await x.next3(); + let d = await x.next4(); +} + +//// [awaitUnionPromise.js] +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var AsyncEnumeratorDone = /** @class */ (function () { + function AsyncEnumeratorDone() { + } + return AsyncEnumeratorDone; +}()); +; +function main() { + return __awaiter(this, void 0, void 0, function () { + var x, a, b, c, d; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + x = null; + return [4 /*yield*/, x.next1()]; + case 1: + a = _a.sent(); + return [4 /*yield*/, x.next2()]; + case 2: + b = _a.sent(); + return [4 /*yield*/, x.next3()]; + case 3: + c = _a.sent(); + return [4 /*yield*/, x.next4()]; + case 4: + d = _a.sent(); + return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/awaitUnionPromise.symbols b/tests/baselines/reference/awaitUnionPromise.symbols new file mode 100644 index 0000000000000..fb26ba1bfaca7 --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/awaitUnionPromise.ts === +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + +interface IAsyncEnumerator { +>IAsyncEnumerator : Symbol(IAsyncEnumerator, Decl(awaitUnionPromise.ts, 3, 30)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) + + next1(): Promise; +>next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + + next2(): Promise | Promise; +>next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + + next3(): Promise; +>next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) + + next4(): Promise; +>next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 9, 26)) +} + +async function main() { +>main : Symbol(main, Decl(awaitUnionPromise.ts, 10, 1)) + + const x: IAsyncEnumerator = null; +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>IAsyncEnumerator : Symbol(IAsyncEnumerator, Decl(awaitUnionPromise.ts, 3, 30)) + + let a = await x.next1(); +>a : Symbol(a, Decl(awaitUnionPromise.ts, 14, 7)) +>x.next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) + + let b = await x.next2(); +>b : Symbol(b, Decl(awaitUnionPromise.ts, 15, 7)) +>x.next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) + + let c = await x.next3(); +>c : Symbol(c, Decl(awaitUnionPromise.ts, 16, 7)) +>x.next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) + + let d = await x.next4(); +>d : Symbol(d, Decl(awaitUnionPromise.ts, 17, 7)) +>x.next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +} diff --git a/tests/baselines/reference/awaitUnionPromise.types b/tests/baselines/reference/awaitUnionPromise.types new file mode 100644 index 0000000000000..f1d91c038de18 --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/awaitUnionPromise.ts === +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; +>AsyncEnumeratorDone : AsyncEnumeratorDone + +interface IAsyncEnumerator { +>IAsyncEnumerator : IAsyncEnumerator +>T : T + + next1(): Promise; +>next1 : () => Promise +>Promise : Promise +>T : T +>AsyncEnumeratorDone : AsyncEnumeratorDone + + next2(): Promise | Promise; +>next2 : () => Promise | Promise +>Promise : Promise +>T : T +>Promise : Promise +>AsyncEnumeratorDone : AsyncEnumeratorDone + + next3(): Promise; +>next3 : () => Promise<{} | T> +>Promise : Promise +>T : T + + next4(): Promise; +>next4 : () => Promise +>Promise : Promise +>T : T +>x : string +} + +async function main() { +>main : () => Promise + + const x: IAsyncEnumerator = null; +>x : IAsyncEnumerator +>IAsyncEnumerator : IAsyncEnumerator +>null : null + + let a = await x.next1(); +>a : number | AsyncEnumeratorDone +>await x.next1() : number | AsyncEnumeratorDone +>x.next1() : Promise +>x.next1 : () => Promise +>x : IAsyncEnumerator +>next1 : () => Promise + + let b = await x.next2(); +>b : number | AsyncEnumeratorDone +>await x.next2() : number | AsyncEnumeratorDone +>x.next2() : Promise | Promise +>x.next2 : () => Promise | Promise +>x : IAsyncEnumerator +>next2 : () => Promise | Promise + + let c = await x.next3(); +>c : number | {} +>await x.next3() : number | {} +>x.next3() : Promise +>x.next3 : () => Promise +>x : IAsyncEnumerator +>next3 : () => Promise + + let d = await x.next4(); +>d : number | { x: string; } +>await x.next4() : number | { x: string; } +>x.next4() : Promise +>x.next4 : () => Promise +>x : IAsyncEnumerator +>next4 : () => Promise +} diff --git a/tests/cases/compiler/awaitUnionPromise.ts b/tests/cases/compiler/awaitUnionPromise.ts new file mode 100644 index 0000000000000..2c8470e97a632 --- /dev/null +++ b/tests/cases/compiler/awaitUnionPromise.ts @@ -0,0 +1,19 @@ +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; + +interface IAsyncEnumerator { + next1(): Promise; + next2(): Promise | Promise; + next3(): Promise; + next4(): Promise; +} + +async function main() { + const x: IAsyncEnumerator = null; + let a = await x.next1(); + let b = await x.next2(); + let c = await x.next3(); + let d = await x.next4(); +} \ No newline at end of file From eebb0447ab3ad06adf252ed9eb81a16e54832a51 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 16 Oct 2017 14:47:43 -0700 Subject: [PATCH 185/246] Fix generated name scope when emitting async functions --- src/compiler/transformers/es2017.ts | 2 +- .../asyncFunctionTempVariableScoping.js | 64 +++++++++++++++++++ .../asyncFunctionTempVariableScoping.symbols | 10 +++ .../asyncFunctionTempVariableScoping.types | 13 ++++ .../asyncFunctionTempVariableScoping.ts | 5 ++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.js create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.symbols create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.types create mode 100644 tests/cases/compiler/asyncFunctionTempVariableScoping.ts diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index d98f227e8c7a8..9fa39da2d2392 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -463,7 +463,7 @@ namespace ts { ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody; + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return createCall( getHelperName("__awaiter"), diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.js b/tests/baselines/reference/asyncFunctionTempVariableScoping.js new file mode 100644 index 0000000000000..b4f8caa650890 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.js @@ -0,0 +1,64 @@ +//// [asyncFunctionTempVariableScoping.ts] +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); + +//// [asyncFunctionTempVariableScoping.js] +// https://github.com/Microsoft/TypeScript/issues/19187 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +}; +var _this = this; +(function (_a) { return __awaiter(_this, void 0, void 0, function () { + var foo = _a.foo, bar = _a.bar, rest = __rest(_a, ["foo", "bar"]); + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _b = bar; + return [4 /*yield*/, foo]; + case 1: return [2 /*return*/, _b.apply(void 0, [_c.sent()])]; + } + }); +}); }); diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols b/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols new file mode 100644 index 0000000000000..578cda3ac7737 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/asyncFunctionTempVariableScoping.ts === +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); +>foo : Symbol(foo, Decl(asyncFunctionTempVariableScoping.ts, 2, 8)) +>bar : Symbol(bar, Decl(asyncFunctionTempVariableScoping.ts, 2, 13)) +>rest : Symbol(rest, Decl(asyncFunctionTempVariableScoping.ts, 2, 18)) +>bar : Symbol(bar, Decl(asyncFunctionTempVariableScoping.ts, 2, 13)) +>foo : Symbol(foo, Decl(asyncFunctionTempVariableScoping.ts, 2, 8)) + diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.types b/tests/baselines/reference/asyncFunctionTempVariableScoping.types new file mode 100644 index 0000000000000..30b2399490368 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/asyncFunctionTempVariableScoping.ts === +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); +>async ({ foo, bar, ...rest }) => bar(await foo) : ({ foo, bar, ...rest }: { [x: string]: any; foo: any; bar: any; }) => Promise +>foo : any +>bar : any +>rest : { [x: string]: any; } +>bar(await foo) : any +>bar : any +>await foo : any +>foo : any + diff --git a/tests/cases/compiler/asyncFunctionTempVariableScoping.ts b/tests/cases/compiler/asyncFunctionTempVariableScoping.ts new file mode 100644 index 0000000000000..c1d52d6da17f6 --- /dev/null +++ b/tests/cases/compiler/asyncFunctionTempVariableScoping.ts @@ -0,0 +1,5 @@ +// @target: es5 +// @lib: es2015 +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); \ No newline at end of file From fd86cd5a2ed120127f41a8a3c62dde9dd38d6a5e Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 16 Oct 2017 22:10:47 +0000 Subject: [PATCH 186/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 6 + .../diagnosticMessages.generated.json.lcl | 17094 ++++++++-------- 2 files changed, 8592 insertions(+), 8508 deletions(-) diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index a2963d878f6c4..ec0503ee41fed 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3990,12 +3990,18 @@ + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index affa7a4834792..bcd7c4e298278 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8509 +1,8587 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - türü olmalıdır.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' kullanın.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + türü olmalıdır.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' kullanın.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 3c452057c2fb88098691bb16a7c490f91d17d6f2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 16 Oct 2017 16:09:16 -0700 Subject: [PATCH 187/246] Add release-2.6 to covered branches --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 27b14739d8b10..d24e155b5804b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ branches: only: - master - release-2.5 + - release-2.6 install: - npm uninstall typescript --no-save From 50628e73c57185b59e12fecde15ce1654fa95e56 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 16:53:33 -0700 Subject: [PATCH 188/246] Do not watch root folders for failed lookup locations and effective type roots Fixes #19170 --- src/compiler/resolutionCache.ts | 72 +++++++-- src/harness/unittests/tscWatchMode.ts | 4 +- .../unittests/tsserverProjectSystem.ts | 142 +++++++++++------- 3 files changed, 148 insertions(+), 70 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 84fffbe6f5ea5..b988da0fd5f13 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -64,6 +64,7 @@ namespace ts { interface DirectoryOfFailedLookupWatch { dir: string; dirPath: Path; + ignore?: true; } export const maxNumberOfFilesToIterateForInvalidation = 256; @@ -319,6 +320,33 @@ namespace ts { return endsWith(dirPath, "/node_modules"); } + function isDirectoryAtleastAtLevelFromFSRoot(dirPath: Path, minLevels: number) { + for (let searchIndex = getRootLength(dirPath); minLevels > 0; minLevels--) { + searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1; + if (searchIndex === 0) { + // Folder isnt at expected minimun levels + return false; + } + } + return true; + } + + function canWatchDirectory(dirPath: Path) { + return isDirectoryAtleastAtLevelFromFSRoot(dirPath, + // When root is "/" do not watch directories like: + // "/", "/user", "/user/username", "/user/username/folderAtRoot" + // When root is "c:/" do not watch directories like: + // "c:/", "c:/folderAtRoot" + dirPath.charCodeAt(0) === CharacterCodes.slash ? 3 : 1); + } + + function filterFSRootDirectoriesToWatch(watchPath: DirectoryOfFailedLookupWatch, dirPath: Path): DirectoryOfFailedLookupWatch { + if (!canWatchDirectory(dirPath)) { + watchPath.ignore = true; + } + return watchPath; + } + function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { return { dir: rootDir, dirPath: rootPath }; @@ -335,7 +363,7 @@ namespace ts { // If the directory is node_modules use it to watch if (isNodeModulesDirectory(dirPath)) { - return { dir, dirPath }; + return filterFSRootDirectoriesToWatch({ dir, dirPath }, getDirectoryPath(dirPath)); } // Use some ancestor of the root directory @@ -350,7 +378,7 @@ namespace ts { } } - return { dir, dirPath }; + return filterFSRootDirectoriesToWatch({ dir, dirPath }, dirPath); } function isPathWithDefaultFailedLookupExtension(path: Path) { @@ -391,13 +419,15 @@ namespace ts { const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0; customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1); } - const { dir, dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); - if (dirWatcher) { - dirWatcher.refCount++; - } - else { - directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }); + const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + if (!ignore) { + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + if (dirWatcher) { + dirWatcher.refCount++; + } + else { + directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }); + } } } } @@ -422,10 +452,12 @@ namespace ts { customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1); } } - const { dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); - // Do not close the watcher yet since it might be needed by other failed lookup locations. - dirWatcher.refCount--; + const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + if (!ignore) { + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + // Do not close the watcher yet since it might be needed by other failed lookup locations. + dirWatcher.refCount--; + } } } @@ -577,7 +609,8 @@ namespace ts { } // we need to assume the directories exist to ensure that we can get all the type root directories that get included - const typeRoots = getEffectiveTypeRoots(options, { directoryExists: returnTrue, getCurrentDirectory }); + // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them + const typeRoots = getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory }); if (typeRoots) { mutateMap( typeRootsWatches, @@ -592,5 +625,16 @@ namespace ts { closeTypeRootsWatch(); } } + + /** + * Use this function to return if directory exists to get type roots to watch + * If we return directory exists then only the paths will be added to type roots + * Hence return true for all directories except root directories which are filtered from watching + */ + function directoryExistsForTypeRootWatch(nodeTypesDirectory: string) { + const dir = getDirectoryPath(getDirectoryPath(nodeTypesDirectory)); + const dirPath = resolutionHost.toPath(dir); + return dirPath === rootPath || canWatchDirectory(dirPath); + } } } diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index b25a7b1eb53c2..24052bd1add2e 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -254,7 +254,7 @@ namespace ts.tscWatch { checkProgramRootFiles(watch(), [file1.path, file2.path]); checkWatchedFiles(host, [configFile.path, file1.path, file2.path, libFile.path]); const configDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true); + checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true); }); // TODO: if watching for config file creation @@ -269,7 +269,7 @@ namespace ts.tscWatch { const host = createWatchedSystem([commonFile1, libFile, configFile]); const watch = createWatchModeWithConfigFile(configFile.path, host); const configDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true); + checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true); checkProgramRootFiles(watch(), [commonFile1.path]); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 4929cbfbaa517..175b579103f57 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -323,14 +323,31 @@ namespace ts.projectSystem { checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles); } - function getNodeModuleDirectories(dir: string) { + function mapCombinedPathsInAncestor(dir: string, path2: string, mapAncestor: (ancestor: string) => boolean) { + dir = normalizePath(dir); const result: string[] = []; forEachAncestorDirectory(dir, ancestor => { - result.push(combinePaths(ancestor, "node_modules")); + if (mapAncestor(ancestor)) { + result.push(combinePaths(ancestor, path2)); + } }); return result; } + function getRootsToWatchWithAncestorDirectory(dir: string, path2: string) { + return mapCombinedPathsInAncestor(dir, path2, ancestor => ancestor.split(directorySeparator).length > 4); + } + + const nodeModules = "node_modules"; + function getNodeModuleDirectories(dir: string) { + return getRootsToWatchWithAncestorDirectory(dir, nodeModules); + } + + export const nodeModulesAtTypes = "node_modules/@types"; + export function getTypeRootsFromLocation(currentDirectory: string) { + return getRootsToWatchWithAncestorDirectory(currentDirectory, nodeModulesAtTypes); + } + function getNumberOfWatchesInvokedForRecursiveWatches(recursiveWatchedDirs: string[], file: string) { return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } @@ -413,15 +430,6 @@ namespace ts.projectSystem { verifyDiagnostics(actual, []); } - export function getTypeRootsFromLocation(currentDirectory: string) { - currentDirectory = normalizePath(currentDirectory); - const result: string[] = []; - forEachAncestorDirectory(currentDirectory, ancestor => { - result.push(combinePaths(ancestor, "node_modules/@types")); - }); - return result; - } - describe("tsserverProjectSystem", () => { const commonFile1: FileOrFolder = { path: "/a/b/commonFile1.ts", @@ -460,7 +468,7 @@ namespace ts.projectSystem { const configFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]); checkWatchedFiles(host, configFiles.concat(libFile.path, moduleFile.path)); checkWatchedDirectories(host, [], /*recursive*/ false); - checkWatchedDirectories(host, ["/a/b/c", ...getTypeRootsFromLocation(getDirectoryPath(appFile.path))], /*recursive*/ true); + checkWatchedDirectories(host, ["/a/b/c", combinePaths(getDirectoryPath(appFile.path), nodeModulesAtTypes)], /*recursive*/ true); }); it("can handle tsconfig file name with difference casing", () => { @@ -532,7 +540,7 @@ namespace ts.projectSystem { // watching all files except one that was open checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]); const configFileDirectory = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, getTypeRootsFromLocation(configFileDirectory).concat(configFileDirectory), /*recursive*/ true); + checkWatchedDirectories(host, [configFileDirectory, combinePaths(configFileDirectory, nodeModulesAtTypes)], /*recursive*/ true); }); it("create configured project with the file list", () => { @@ -621,7 +629,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(commonFile1.path); const configFileDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, getTypeRootsFromLocation(configFileDir).concat(configFileDir), /*recursive*/ true); + checkWatchedDirectories(host, [configFileDir, combinePaths(configFileDir, nodeModulesAtTypes)], /*recursive*/ true); checkNumberOfConfiguredProjects(projectService, 1); const project = configuredProjectAt(projectService, 0); @@ -2433,7 +2441,7 @@ namespace ts.projectSystem { checkProjectActualFiles(project, map(files, file => file.path)); checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path)); checkWatchedDirectories(host, [], /*recursive*/ false); - const watchedRecursiveDirectories = getTypeRootsFromLocation("/a/b"); + const watchedRecursiveDirectories = ["/a/b/node_modules/@types"]; watchedRecursiveDirectories.push("/a/b"); checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); @@ -2459,7 +2467,8 @@ namespace ts.projectSystem { }); - it("Failed lookup locations are uses parent most node_modules directory", () => { + it("Failed lookup locations uses parent most node_modules directory", () => { + const root = "/user/username/rootfolder"; const file1: FileOrFolder = { path: "/a/b/src/file1.ts", content: 'import { classc } from "module1"' @@ -2479,9 +2488,11 @@ namespace ts.projectSystem { }; const configFile: FileOrFolder = { path: "/a/b/src/tsconfig.json", - content: JSON.stringify({ files: [file1.path] }) + content: JSON.stringify({ files: ["file1.ts"] }) }; - const files = [file1, module1, module2, module3, configFile, libFile]; + const nonLibFiles = [file1, module1, module2, module3, configFile]; + nonLibFiles.forEach(f => f.path = root + f.path); + const files = nonLibFiles.concat(libFile); const host = createServerHost(files); const projectService = createProjectService(host); projectService.openClientFile(file1.path); @@ -2491,8 +2502,8 @@ namespace ts.projectSystem { checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]); checkWatchedDirectories(host, [], /*recursive*/ false); - const watchedRecursiveDirectories = getTypeRootsFromLocation("/a/b/src"); - watchedRecursiveDirectories.push("/a/b/src", "/a/b/node_modules"); + const watchedRecursiveDirectories = getTypeRootsFromLocation(root + "/a/b/src"); + watchedRecursiveDirectories.push(`${root}/a/b/src`, `${root}/a/b/node_modules`); checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); }); }); @@ -4682,7 +4693,6 @@ namespace ts.projectSystem { } const f2Lookups = getLocationsForModuleLookup("f2"); callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1); - const typeRootLocations = getTypeRootsFromLocation(getDirectoryPath(root.path)); const f2DirLookups = getLocationsForDirectoryLookup(); callsTrackingHost.verifyCalledOnEachEntry(CalledMapsWithSingleArg.directoryExists, f2DirLookups); callsTrackingHost.verifyNoCall(CalledMapsWithSingleArg.getDirectories); @@ -4693,7 +4703,7 @@ namespace ts.projectSystem { verifyImportedDiagnostics(); const f1Lookups = f2Lookups.map(s => s.replace("f2", "f1")); f1Lookups.length = f1Lookups.indexOf(imported.path) + 1; - const f1DirLookups = ["/c/d", "/c", ...typeRootLocations]; + const f1DirLookups = ["/c/d", "/c", ...mapCombinedPathsInAncestor(getDirectoryPath(root.path), nodeModulesAtTypes, returnTrue)]; vertifyF1Lookups(); // setting compiler options discards module resolution cache @@ -4744,13 +4754,12 @@ namespace ts.projectSystem { function getLocationsForDirectoryLookup() { const result = createMap(); - // Type root - typeRootLocations.forEach(location => result.set(location, 1)); forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { // To resolve modules result.set(ancestor, 2); // for type roots - result.set(combinePaths(ancestor, `node_modules`), 1); + result.set(combinePaths(ancestor, nodeModules), 1); + result.set(combinePaths(ancestor, nodeModulesAtTypes), 1); }); return result; } @@ -4990,15 +4999,20 @@ namespace ts.projectSystem { describe("Verify npm install in directory with tsconfig file works when", () => { function verifyNpmInstall(timeoutDuringPartialInstallation: boolean) { - const app: FileOrFolder = { + const root = "/user/username/rootfolder/otherfolder"; + const getRootedFileOrFolder = (fileOrFolder: FileOrFolder) => { + fileOrFolder.path = root + fileOrFolder.path; + return fileOrFolder; + }; + const app: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/app.ts", content: "import _ from 'lodash';" - }; - const tsconfigJson: FileOrFolder = { + }); + const tsconfigJson: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/tsconfig.json", content: '{ "compilerOptions": { } }' - }; - const packageJson: FileOrFolder = { + }); + const packageJson: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/package.json", content: ` { @@ -5022,7 +5036,7 @@ namespace ts.projectSystem { "license": "ISC" } ` - }; + }); const appFolder = getDirectoryPath(app.path); const projectFiles = [app, libFile, tsconfigJson]; const typeRootDirectories = getTypeRootsFromLocation(getDirectoryPath(tsconfigJson.path)); @@ -5053,16 +5067,16 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", "content": "declare const observableSymbol: symbol;\nexport default observableSymbol;\n" }, { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib" }, { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;" }, - ]; + ].map(getRootedFileOrFolder); verifyAfterPartialOrCompleteNpmInstall(2); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/lib" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/add/operator" }, { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/package.json", "content": "{\n \"name\": \"@types/lodash\",\n \"version\": \"4.14.74\",\n \"description\": \"TypeScript definitions for Lo-Dash\",\n \"license\": \"MIT\",\n \"contributors\": [\n {\n \"name\": \"Brian Zengel\",\n \"url\": \"https://github.com/bczengel\"\n },\n {\n \"name\": \"Ilya Mochalov\",\n \"url\": \"https://github.com/chrootsu\"\n },\n {\n \"name\": \"Stepan Mikhaylyuk\",\n \"url\": \"https://github.com/stepancar\"\n },\n {\n \"name\": \"Eric L Anderson\",\n \"url\": \"https://github.com/ericanderson\"\n },\n {\n \"name\": \"AJ Richardson\",\n \"url\": \"https://github.com/aj-r\"\n },\n {\n \"name\": \"Junyoung Clare Jang\",\n \"url\": \"https://github.com/ailrun\"\n }\n ],\n \"main\": \"\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://www.github.com/DefinitelyTyped/DefinitelyTyped.git\"\n },\n \"scripts\": {},\n \"dependencies\": {},\n \"typesPublisherContentHash\": \"12af578ffaf8d86d2df37e591857906a86b983fa9258414326544a0fe6af0de8\",\n \"typeScriptVersion\": \"2.2\"\n}" }, { "path": "/a/b/node_modules/.staging/lodash-b0733faa/index.js", "content": "module.exports = require('./lodash');" }, { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" } - ); + ].map(getRootedFileOrFolder)); // Since we didnt add any supported extension file, there wont be any timeout scheduled verifyAfterPartialOrCompleteNpmInstall(0); @@ -5070,27 +5084,27 @@ namespace ts.projectSystem { filesAndFoldersToAdd.length--; verifyAfterPartialOrCompleteNpmInstall(0); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/rxjs-22375c61/bundles" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/operator" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" }, { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", "content": "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" } - ); + ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(2); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/scheduler" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/util" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/symbol" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/testing" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", "content": "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"rxjs@5.4.3\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://git@github.com/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" } - ); + ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(0); // remove /a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041 filesAndFoldersToAdd.length--; // and add few more folders/files - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/symbol-observable" }, { "path": "/a/b/node_modules/@types" }, { "path": "/a/b/node_modules/@types/lodash" }, @@ -5098,7 +5112,7 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/rxjs" }, { "path": "/a/b/node_modules/typescript" }, { "path": "/a/b/node_modules/.bin" } - ); + ].map(getRootedFileOrFolder)); // From the type root update verifyAfterPartialOrCompleteNpmInstall(2); @@ -5108,7 +5122,7 @@ namespace ts.projectSystem { .replace(/[\-\.][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w]/g, ""); }); - const lodashIndexPath = "/a/b/node_modules/@types/lodash/index.d.ts"; + const lodashIndexPath = root + "/a/b/node_modules/@types/lodash/index.d.ts"; projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)); // we would now not have failed lookup in the parent of appFolder since lodash is available recursiveWatchedDirectories.length = 1; @@ -5570,27 +5584,32 @@ namespace ts.projectSystem { }); describe("resolution when resolution cache size", () => { - function verifyWithMaxCacheLimit(limitHit: boolean) { + function verifyWithMaxCacheLimit(limitHit: boolean, useSlashRootAsSomeNotRootFolderInUserDirectory: boolean) { + const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory ? "/user/username/rootfolder/otherfolder/" : "/"; const file1: FileOrFolder = { - path: "/a/b/project/file1.ts", + path: rootFolder + "a/b/project/file1.ts", content: 'import a from "file2"' }; const file2: FileOrFolder = { - path: "/a/b/node_modules/file2.d.ts", + path: rootFolder + "a/b/node_modules/file2.d.ts", content: "export class a { }" }; const file3: FileOrFolder = { - path: "/a/b/project/file3.ts", + path: rootFolder + "a/b/project/file3.ts", content: "export class c { }" }; const configFile: FileOrFolder = { - path: "/a/b/project/tsconfig.json", + path: rootFolder + "a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { typeRoots: [] } }) }; const projectFiles = [file1, file3, libFile, configFile]; const openFiles = [file1.path]; - const watchedRecursiveDirectories = ["/a/b/project", "/a/b/node_modules", "/a/node_modules", "/node_modules"]; + const watchedRecursiveDirectories = useSlashRootAsSomeNotRootFolderInUserDirectory ? + // Folders of node_modules lookup not in changedRoot + ["a/b/project", "a/b/node_modules", "a/node_modules", "node_modules"].map(v => rootFolder + v) : + // Folder of tsconfig + ["/a/b/project"]; const host = createServerHost(projectFiles); const { session, verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host); const projectService = session.getProjectService(); @@ -5618,15 +5637,22 @@ namespace ts.projectSystem { projectFiles.push(file2); host.reloadFS(projectFiles); host.runQueuedTimeoutCallbacks(); - watchedRecursiveDirectories.length = 2; + if (useSlashRootAsSomeNotRootFolderInUserDirectory) { + watchedRecursiveDirectories.length = 2; + } + else { + // file2 addition wont be detected + projectFiles.pop(); + assert.isTrue(host.fileExists(file2.path)); + } verifyProject(); - verifyProjectsUpdatedInBackgroundEventHandler([{ + verifyProjectsUpdatedInBackgroundEventHandler(useSlashRootAsSomeNotRootFolderInUserDirectory ? [{ eventName: server.ProjectsUpdatedInBackgroundEvent, data: { openFiles } - }]); + }] : []); function verifyProject() { checkProjectActualFiles(project, map(projectFiles, file => file.path)); @@ -5635,12 +5661,20 @@ namespace ts.projectSystem { } } - it("limit not hit", () => { - verifyWithMaxCacheLimit(/*limitHit*/ false); + it("limit not hit and project is not at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ false, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true); + }); + + it("limit hit and project is not at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ true, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true); + }); + + it("limit not hit and project is at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ false, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false); }); - it("limit hit", () => { - verifyWithMaxCacheLimit(/*limitHit*/ true); + it("limit hit and project is at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ true, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false); }); }); } From 92d191990adee9cef63f6407ff2e2bd171a3a7a0 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 17 Oct 2017 04:10:06 +0000 Subject: [PATCH 189/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17048 ++++++++-------- 1 file changed, 8563 insertions(+), 8485 deletions(-) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 79859d9bae27a..38946acf4725d 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8486 +1,8564 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - oder - erforderlich, z. B. "{0}" oder "{1}".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - " sein.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + oder - erforderlich, z. B. "{0}" oder "{1}".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + " sein.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 1af25ae9f1d3ee9076af6439444c93ab21b57f69 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 17 Oct 2017 16:10:05 +0000 Subject: [PATCH 190/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 75 ++++++++++++++++--- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- 5 files changed, 307 insertions(+), 64 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 075923ea43857..d27b3a500b880 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -801,6 +801,12 @@ + + + + + + @@ -1338,6 +1344,18 @@ + + + + + + + + + + + + @@ -1485,6 +1503,12 @@ + + + + + + @@ -1892,12 +1916,12 @@ - - + + - + @@ -2013,6 +2037,12 @@ + + + + + + @@ -3795,6 +3825,18 @@ + + + + + + + + + + + + @@ -3987,21 +4029,15 @@ - + - - - - + - + - - - - + @@ -7263,6 +7299,12 @@ + + + + + + @@ -7743,6 +7785,12 @@ + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 026f10b37be90..43073f7cab335 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -801,6 +801,12 @@ + + + + + + @@ -1338,6 +1344,18 @@ + + + + + + + + + + + + @@ -1485,6 +1503,12 @@ + + + + + + @@ -1892,12 +1916,12 @@ - - + + - + @@ -2013,6 +2037,12 @@ + + + + + + @@ -3795,6 +3825,18 @@ + + + + + + + + + + + + @@ -3987,21 +4029,15 @@ - + - - - - + - + - - - - + @@ -7263,6 +7299,12 @@ + + + + + + @@ -7743,6 +7785,12 @@ + + + + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index b978802c56409..727bf964abf21 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,12 @@ + + + + + + @@ -1329,6 +1335,18 @@ + + + + + + + + + + + + @@ -1476,6 +1494,12 @@ + + + + + + @@ -1883,12 +1907,12 @@ - - + + - + @@ -2004,6 +2028,12 @@ + + + + + + @@ -3786,6 +3816,18 @@ + + + + + + + + + + + + @@ -3978,21 +4020,15 @@ - + - - - - + - + - - - - + @@ -7254,6 +7290,12 @@ + + + + + + @@ -7734,6 +7776,12 @@ + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3a8512e54b238..4ae9e7d5e5697 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -782,6 +782,12 @@ + + + + + + @@ -1313,6 +1319,18 @@ + + + + + + + + + + + + @@ -1460,6 +1478,12 @@ + + + + + + @@ -1867,10 +1891,13 @@ - - + + + + + @@ -1982,6 +2009,12 @@ + + + + + + @@ -3758,6 +3791,18 @@ + + + + + + + + + + + + @@ -3950,21 +3995,15 @@ - + - - - - + - + - - - - + @@ -7217,6 +7256,12 @@ + + + + + + @@ -7697,6 +7742,12 @@ + + + + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index aac4d18cd6799..b0e6c4b3495f0 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -791,6 +791,12 @@ + + + + + + @@ -1328,6 +1334,18 @@ + + + + + + + + + + + + @@ -1475,6 +1493,12 @@ + + + + + + @@ -1882,12 +1906,12 @@ - - + + - + @@ -2003,6 +2027,12 @@ + + + + + + @@ -3785,6 +3815,18 @@ + + + + + + + + + + + + @@ -3977,21 +4019,15 @@ - + - - - - + - + - - - - + @@ -7253,6 +7289,12 @@ + + + + + + @@ -7733,6 +7775,12 @@ + + + + + + From 08d7e182cd40e152a3ab8291a10fcb40913f0caa Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 Oct 2017 09:56:04 -0700 Subject: [PATCH 191/246] Mark fresh spread objects w/ContainsObjectLiteral --- 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 69a46ed6cb236..f30d956e311df 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7971,7 +7971,7 @@ namespace ts { const spread = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); spread.flags |= propagatedFlags; - spread.flags |= TypeFlags.FreshLiteral; + spread.flags |= TypeFlags.FreshLiteral | TypeFlags.ContainsObjectLiteral; (spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral; spread.symbol = symbol; return spread; From e58aa100687e3c1e92b04d927cd78d64f233ea3e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 Oct 2017 09:56:28 -0700 Subject: [PATCH 192/246] Test excess property checks of spreads of unions. --- .../excessPropertyCheckWithUnions.errors.txt | 6 +++++ .../excessPropertyCheckWithUnions.js | 17 ++++++++++++ .../excessPropertyCheckWithUnions.symbols | 25 +++++++++++++++++ .../excessPropertyCheckWithUnions.types | 27 +++++++++++++++++++ .../reference/spreadInvalidArgumentType.types | 2 +- .../compiler/excessPropertyCheckWithUnions.ts | 7 +++++ 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index 3b7e5a787d2aa..9fbbb00160540 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -96,4 +96,10 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type // these two are not reported because there are two discriminant properties over = { a: 1, b: 1, first: "ok", second: "error" } over = { a: 1, b: 1, first: "ok", third: "error" } + + // Freshness disappears after spreading a union + declare let t0: { a: any, b: any } | { d: any, e: any } + declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any } + let t2 = { ...t1 } + t0 = t2 \ No newline at end of file diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js index c6da660b52dde..c6b45123cce76 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.js +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -49,9 +49,24 @@ let over: Overlapping // these two are not reported because there are two discriminant properties over = { a: 1, b: 1, first: "ok", second: "error" } over = { a: 1, b: 1, first: "ok", third: "error" } + +// Freshness disappears after spreading a union +declare let t0: { a: any, b: any } | { d: any, e: any } +declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any } +let t2 = { ...t1 } +t0 = t2 //// [excessPropertyCheckWithUnions.js] +"use strict"; +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; var wrong = { tag: "T", a1: "extra" }; wrong = { tag: "A", d20: 12 }; wrong = { tag: "D" }; @@ -72,3 +87,5 @@ var over; // these two are not reported because there are two discriminant properties over = { a: 1, b: 1, first: "ok", second: "error" }; over = { a: 1, b: 1, first: "ok", third: "error" }; +var t2 = __assign({}, t1); +t0 = t2; diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols index 332166e396c8f..7778c6bf21699 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols @@ -142,3 +142,28 @@ over = { a: 1, b: 1, first: "ok", third: "error" } >first : Symbol(first, Decl(excessPropertyCheckWithUnions.ts, 49, 20)) >third : Symbol(third, Decl(excessPropertyCheckWithUnions.ts, 49, 33)) +// Freshness disappears after spreading a union +declare let t0: { a: any, b: any } | { d: any, e: any } +>t0 : Symbol(t0, Decl(excessPropertyCheckWithUnions.ts, 52, 11)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 52, 17)) +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 52, 25)) +>d : Symbol(d, Decl(excessPropertyCheckWithUnions.ts, 52, 38)) +>e : Symbol(e, Decl(excessPropertyCheckWithUnions.ts, 52, 46)) + +declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any } +>t1 : Symbol(t1, Decl(excessPropertyCheckWithUnions.ts, 53, 11)) +>a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 53, 17)) +>b : Symbol(b, Decl(excessPropertyCheckWithUnions.ts, 53, 25)) +>c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 53, 33)) +>c : Symbol(c, Decl(excessPropertyCheckWithUnions.ts, 53, 46)) +>d : Symbol(d, Decl(excessPropertyCheckWithUnions.ts, 53, 54)) +>e : Symbol(e, Decl(excessPropertyCheckWithUnions.ts, 53, 62)) + +let t2 = { ...t1 } +>t2 : Symbol(t2, Decl(excessPropertyCheckWithUnions.ts, 54, 3)) +>t1 : Symbol(t1, Decl(excessPropertyCheckWithUnions.ts, 53, 11)) + +t0 = t2 +>t0 : Symbol(t0, Decl(excessPropertyCheckWithUnions.ts, 52, 11)) +>t2 : Symbol(t2, Decl(excessPropertyCheckWithUnions.ts, 54, 3)) + diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.types b/tests/baselines/reference/excessPropertyCheckWithUnions.types index 1d6bdd32eb269..78f5c025b380d 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.types +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.types @@ -194,3 +194,30 @@ over = { a: 1, b: 1, first: "ok", third: "error" } >third : string >"error" : "error" +// Freshness disappears after spreading a union +declare let t0: { a: any, b: any } | { d: any, e: any } +>t0 : { a: any; b: any; } | { d: any; e: any; } +>a : any +>b : any +>d : any +>e : any + +declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any } +>t1 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } +>a : any +>b : any +>c : any +>c : any +>d : any +>e : any + +let t2 = { ...t1 } +>t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } +>{ ...t1 } : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } +>t1 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } + +t0 = t2 +>t0 = t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } +>t0 : { a: any; b: any; } | { d: any; e: any; } +>t2 : { a: any; b: any; c: any; } | { c: any; d: any; e: any; } + diff --git a/tests/baselines/reference/spreadInvalidArgumentType.types b/tests/baselines/reference/spreadInvalidArgumentType.types index 244d851589331..ae85189962215 100644 --- a/tests/baselines/reference/spreadInvalidArgumentType.types +++ b/tests/baselines/reference/spreadInvalidArgumentType.types @@ -89,7 +89,7 @@ function f(p1: T, p2: T[]) { >p1 : T var o2 = { ...p2 }; // OK ->o2 : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } +>o2 : { [x: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >{ ...p2 } : { [n: number]: T; length: number; toString(): string; toLocaleString(): string; push(...items: T[]): number; pop(): T; concat(...items: ReadonlyArray[]): T[]; concat(...items: (T | ReadonlyArray)[]): T[]; join(separator?: string): string; reverse(): T[]; shift(): T; slice(start?: number, end?: number): T[]; sort(compareFn?: (a: T, b: T) => number): T[]; splice(start: number, deleteCount?: number): T[]; splice(start: number, deleteCount: number, ...items: T[]): T[]; unshift(...items: T[]): number; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[]; filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T; reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; } >p2 : T[] diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts index 9a7968fe5114e..d5a2327380e76 100644 --- a/tests/cases/compiler/excessPropertyCheckWithUnions.ts +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -1,3 +1,4 @@ +// @strict: true type ADT = { tag: "A", a1: string @@ -48,3 +49,9 @@ let over: Overlapping // these two are not reported because there are two discriminant properties over = { a: 1, b: 1, first: "ok", second: "error" } over = { a: 1, b: 1, first: "ok", third: "error" } + +// Freshness disappears after spreading a union +declare let t0: { a: any, b: any } | { d: any, e: any } +declare let t1: { a: any, b: any, c: any } | { c: any, d: any, e: any } +let t2 = { ...t1 } +t0 = t2 From 2b566b9a536e082fc05896a0ddbae2eab165f86a Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Oct 2017 10:20:11 -0700 Subject: [PATCH 193/246] Add exported members of all project files in the global completion list (#19069) * checker.ts: Remove null check on symbols * tsserverProjectSystem.ts: add two tests * client.ts, completions.ts, types.ts: Add codeActions member to CompletionEntryDetails * protocol.ts, session.ts: Add codeActions member to CompletionEntryDetails protocol * protocol.ts, session.ts, types.ts: add hasAction to CompletionEntry * session.ts, services.ts, types.ts: Add formattingOptions parameter to getCompletionEntryDetails * completions.ts: define SymbolOriginInfo type * completions.ts, services.ts: Add allSourceFiles parameter to getCompletionsAtPosition * completions.ts, services.ts: Plumb allSourceFiles into new function getSymbolsFromOtherSourceFileExports inside getCompletionData * completions.ts: add symbolToOriginInfoMap parameter to getCompletionEntriesFromSymbols and to return value of getCompletionData * utilities.ts: Add getOtherModuleSymbols, getUniqueSymbolIdAsString, getUniqueSymbolId * completions.ts: Set CompletionEntry.hasAction when symbol is found in symbolToOriginInfoMap (meaning there's an import action) * completions.ts: Populate list with possible exports (implement getSymbolsFromOtherSourceFileExports) * completions.ts, services.ts: Plumb host and rulesProvider into getCompletionEntryDetails * completions.ts: Add TODO comment * importFixes.ts: Add types ImportDeclarationMap and ImportCodeFixContext * Move getImportDeclarations into getCodeActionForImport, immediately after the implementation * importFixes.ts: Move createChangeTracker into getCodeActionForImport, immediately after getImportDeclarations * importFixes.ts: Add convertToImportCodeFixContext function and reference it from the getCodeActions lambda * importFixes.ts: Add context: ImportCodeFixContext parameter to getCodeActionForImport, update call sites, destructure it, use compilerOptions in getModuleSpecifierForNewImport * importFixes.ts: Remove moduleSymbol parameter from getImportDeclarations and use the ambient one * importFixes.ts: Use cachedImportDeclarations from context in getCodeActionForImport * importFixes.ts: Move createCodeAction out, immediately above convertToImportCodeFixContext * Move the declaration for lastImportDeclaration out of the getCodeActions lambda into getCodeActionForImport * importFixes.ts: Use symbolToken in getCodeActionForImport * importFixes.ts: Remove useCaseSensitiveFileNames altogether from getCodeActions lambda * importFixes.ts: Remove local getUniqueSymbolId function and add checker parameter to calls to it * importFixes.ts: Move getCodeActionForImport out into an export, immediately below convertToImportCodeFixContext * completions.ts: In getCompletionEntryDetails, if there's symbolOriginInfo, call getCodeActionForImport * importFixes.ts: Create and use importFixContext within getCodeActions lambda * importFixes.ts: Use local newLineCharacter instead of context.newLineCharacter in getCodeActionForImport * importFixes.ts: Use local host instead of context.host in getCodeActionForImport * importFixes.ts: Remove dummy getCanonicalFileName line * Filter symbols after gathering exports instead of before * Lint * Test, fix bugs, refactor * Suggestions from code review * Update api baseline * Fix bug if previousToken is not an Identifier * Replace `startsWith` with `stringContainsCharactersInOrder` --- src/compiler/checker.ts | 18 +- src/compiler/commandLineParser.ts | 4 +- src/compiler/core.ts | 30 + src/compiler/diagnosticMessages.json | 4 +- src/compiler/moduleNameResolver.ts | 6 +- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 15 + src/harness/fourslash.ts | 67 +- src/harness/harnessLanguageService.ts | 4 +- src/server/client.ts | 4 +- src/server/protocol.ts | 10 + src/server/session.ts | 23 +- src/services/codeFixProvider.ts | 4 +- src/services/codefixes/importFixes.ts | 993 +++++++++--------- src/services/completions.ts | 206 +++- src/services/pathCompletions.ts | 2 +- src/services/refactorProvider.ts | 4 +- src/services/services.ts | 10 +- src/services/shims.ts | 9 +- src/services/textChanges.ts | 13 +- src/services/types.ts | 5 +- src/services/utilities.ts | 8 +- .../reference/api/tsserverlibrary.d.ts | 22 +- tests/baselines/reference/api/typescript.d.ts | 13 +- ...letionsImport_default_addToNamedImports.ts | 19 + ...ionsImport_default_addToNamespaceImport.ts | 18 + ...Import_default_alreadyExistedWithRename.ts | 20 + ...letionsImport_default_didNotExistBefore.ts | 19 + .../completionsImport_fromAmbientModule.ts | 18 + .../fourslash/completionsImport_matching.ts | 22 + ...mpletionsImport_named_addToNamedImports.ts | 19 + ...mpletionsImport_named_didNotExistBefore.ts | 20 + ...tionsImport_named_namespaceImportExists.ts | 20 + ...pletionsImport_previousTokenIsSemicolon.ts | 11 + tests/cases/fourslash/fourslash.ts | 23 +- .../importNameCodeFixOptionalImport0.ts | 2 +- 36 files changed, 1104 insertions(+), 582 deletions(-) create mode 100644 tests/cases/fourslash/completionsImport_default_addToNamedImports.ts create mode 100644 tests/cases/fourslash/completionsImport_default_addToNamespaceImport.ts create mode 100644 tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts create mode 100644 tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts create mode 100644 tests/cases/fourslash/completionsImport_fromAmbientModule.ts create mode 100644 tests/cases/fourslash/completionsImport_matching.ts create mode 100644 tests/cases/fourslash/completionsImport_named_addToNamedImports.ts create mode 100644 tests/cases/fourslash/completionsImport_named_didNotExistBefore.ts create mode 100644 tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts create mode 100644 tests/cases/fourslash/completionsImport_previousTokenIsSemicolon.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 69a46ed6cb236..ee6930e1b4ab1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -314,6 +314,7 @@ namespace ts { const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); const globals = createSymbolTable(); + let ambientModulesCache: Symbol[] | undefined; /** * List of every ambient module with a "*" wildcard. * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. @@ -25586,13 +25587,16 @@ namespace ts { } function getAmbientModules(): Symbol[] { - const result: Symbol[] = []; - globals.forEach((global, sym) => { - if (ambientModuleSymbolRegex.test(unescapeLeadingUnderscores(sym))) { - result.push(global); - } - }); - return result; + if (!ambientModulesCache) { + ambientModulesCache = []; + globals.forEach((global, sym) => { + // No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module. + if (ambientModuleSymbolRegex.test(sym as string)) { + ambientModulesCache.push(global); + } + }); + } + return ambientModulesCache; } function checkGrammarImportCallExpression(node: ImportCall): boolean { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index af0697a12d914..2eca9dca05c4a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1183,8 +1183,8 @@ namespace ts { } } - function isDoubleQuotedString(node: Node) { - return node.kind === SyntaxKind.StringLiteral && getSourceTextOfNodeFromSourceFile(sourceFile, node).charCodeAt(0) === CharacterCodes.doubleQuote; + function isDoubleQuotedString(node: Node): boolean { + return isStringLiteral(node) && isStringDoubleQuoted(node, sourceFile); } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f838d6abfef22..542435b84f901 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -191,6 +191,18 @@ namespace ts { } return undefined; } + + /** Like `forEach`, but suitable for use with numbers and strings (which may be falsy). */ + export function firstDefined(array: ReadonlyArray | undefined, callback: (element: T, index: number) => U | undefined): U | undefined { + for (let i = 0; i < array.length; i++) { + const result = callback(array[i], i); + if (result !== undefined) { + return result; + } + } + return undefined; + } + /** * Iterates through the parent chain of a node and performs the callback on each parent until the callback * returns a truthy value, then returns that value. @@ -261,6 +273,16 @@ namespace ts { return undefined; } + export function findLast(array: ReadonlyArray, predicate: (element: T, index: number) => boolean): T | undefined { + for (let i = array.length - 1; i >= 0; i--) { + const value = array[i]; + if (predicate(value, i)) { + return value; + } + } + return undefined; + } + /** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */ export function findIndex(array: ReadonlyArray, predicate: (element: T, index: number) => boolean): number { for (let i = 0; i < array.length; i++) { @@ -1147,6 +1169,14 @@ namespace ts { return result; } + export function arrayToNumericMap(array: ReadonlyArray, makeKey: (value: T) => number): T[] { + const result: T[] = []; + for (const value of array) { + result[makeKey(value)] = value; + } + return result; + } + /** * Creates a set from the elements of an array. * diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8cd5088049c65..f33cc4449f936 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3661,7 +3661,7 @@ "category": "Error", "code": 90010 }, - "Import {0} from {1}.": { + "Import '{0}' from \"{1}\".": { "category": "Message", "code": 90013 }, @@ -3669,7 +3669,7 @@ "category": "Message", "code": 90014 }, - "Add {0} to existing import declaration from {1}.": { + "Add '{0}' to existing import declaration from \"{1}\".": { "category": "Message", "code": 90015 }, diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 08178d3d16aad..a0e045cf0f259 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -128,7 +128,11 @@ namespace ts { } } - export function getEffectiveTypeRoots(options: CompilerOptions, host: { directoryExists?: (directoryName: string) => boolean, getCurrentDirectory?: () => string }): string[] | undefined { + export interface GetEffectiveTypeRootsHost { + directoryExists?(directoryName: string): boolean; + getCurrentDirectory?(): string; + } + export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined { if (options.typeRoots) { return options.typeRoots; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42e8292b13bd8..6226e4f98c723 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1055,6 +1055,7 @@ namespace ts { export interface StringLiteral extends LiteralExpression { kind: SyntaxKind.StringLiteral; /* @internal */ textSourceNode?: Identifier | StringLiteral | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms). + /** Note: this is only set when synthesizing a node, not during parsing. */ /* @internal */ singleQuote?: boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c4d3de453ba5c..f907cce85b1f3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -520,6 +520,17 @@ namespace ts { } } + /* @internal */ + export function isAnyImportSyntax(node: Node): node is AnyImportSyntax { + switch (node.kind) { + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + return true; + default: + return false; + } + } + // Gets the nearest enclosing block scope container that has the provided node // as a descendant, that is not the provided node. export function getEnclosingBlockScopeContainer(node: Node): Node { @@ -1375,6 +1386,10 @@ namespace ts { return charCode === CharacterCodes.singleQuote || charCode === CharacterCodes.doubleQuote; } + export function isStringDoubleQuoted(string: StringLiteral, sourceFile: SourceFile): boolean { + return getSourceTextOfNodeFromSourceFile(sourceFile, string).charCodeAt(0) === CharacterCodes.doubleQuote; + } + /** * Returns true if the node is a variable declaration whose initializer is a function expression. * This function does not test if the node is in a JavaScript file or not. diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index de6d92eda05ed..493b0187b57ad 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -783,10 +783,10 @@ namespace FourSlash { }); } - public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) { + public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean) { const completions = this.getCompletionListAtCaret(); if (completions) { - this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind, spanIndex); + this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind, spanIndex, hasAction); } else { this.raiseError(`No completions at position '${this.currentCaretPosition}' when looking for '${symbol}'.`); @@ -1127,7 +1127,7 @@ Actual: ${stringify(fullActual)}`); } private getCompletionEntryDetails(entryName: string) { - return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName); + return this.languageService.getCompletionEntryDetails(this.activeFile.fileName, this.currentCaretPosition, entryName, this.formatCodeSettings); } private getReferencesAtCaret() { @@ -2289,6 +2289,29 @@ Actual: ${stringify(fullActual)}`); this.applyCodeActions(this.getCodeFixActions(fileName, errorCode), index); } + public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) { + this.goToMarker(markerName); + + const actualCompletion = this.getCompletionListAtCaret().entries.find(e => e.name === options.name); + + if (!actualCompletion.hasAction) { + this.raiseError(`Completion for ${options.name} does not have an associated action.`); + } + + const details = this.getCompletionEntryDetails(options.name); + if (details.codeActions.length !== 1) { + this.raiseError(`Expected one code action, got ${details.codeActions.length}`); + } + + if (details.codeActions[0].description !== options.description) { + this.raiseError(`Expected description to be:\n${options.description}\ngot:\n${details.codeActions[0].description}`); + } + + this.applyCodeActions(details.codeActions); + + this.verifyNewContent(options); + } + public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) { const ranges = this.getRanges(); if (ranges.length !== 1) { @@ -2360,6 +2383,10 @@ Actual: ${stringify(fullActual)}`); this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false); } + this.verifyNewContent(options); + } + + private verifyNewContent(options: FourSlashInterface.NewContentOptions) { if (options.newFileContent) { assert(!options.newRangeContent); this.verifyCurrentFileContent(options.newFileContent); @@ -2933,7 +2960,15 @@ Actual: ${stringify(fullActual)}`); return text.substring(startPos, endPos); } - private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string, spanIndex?: number) { + private assertItemInCompletionList( + items: ts.CompletionEntry[], + name: string, + text: string | undefined, + documentation: string | undefined, + kind: string | undefined, + spanIndex: number | undefined, + hasAction: boolean | undefined, + ) { for (const item of items) { if (item.name === name) { if (documentation !== undefined || text !== undefined) { @@ -2956,6 +2991,8 @@ Actual: ${stringify(fullActual)}`); assert.isTrue(TestState.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + name)); } + assert.equal(item.hasAction, hasAction); + return; } } @@ -3669,12 +3706,12 @@ namespace FourSlashInterface { // 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, spanIndex?: number) { + public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number, hasAction?: boolean) { if (this.negative) { this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind, spanIndex); } else { - this.state.verifyCompletionListContains(symbol, text, documentation, kind, spanIndex); + this.state.verifyCompletionListContains(symbol, text, documentation, kind, spanIndex, hasAction); } } @@ -3999,6 +4036,10 @@ namespace FourSlashInterface { this.state.getAndApplyCodeActions(errorCode, index); } + public applyCodeActionFromCompletion(markerName: string, options: VerifyCompletionActionOptions): void { + this.state.applyCodeActionFromCompletion(markerName, options); + } + public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void { this.state.verifyImportFixAtPosition(expectedTextArray, errorCode); } @@ -4396,12 +4437,20 @@ namespace FourSlashInterface { isNewIdentifierLocation?: boolean; } - export interface VerifyCodeFixOptions { - description: string; - // One of these should be defined. + export interface NewContentOptions { + // Exactly one of these should be defined. newFileContent?: string; newRangeContent?: string; + } + + export interface VerifyCodeFixOptions extends NewContentOptions { + description: string; errorCode?: number; index?: number; } + + export interface VerifyCompletionActionOptions extends NewContentOptions { + name: string; + description: string; + } } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index ad79c96d833f8..527824ee145aa 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -405,8 +405,8 @@ namespace Harness.LanguageService { getCompletionsAtPosition(fileName: string, position: number): ts.CompletionInfo { return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position)); } - getCompletionEntryDetails(fileName: string, position: number, entryName: string): ts.CompletionEntryDetails { - return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName)); + getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: ts.FormatCodeOptions): ts.CompletionEntryDetails { + return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName, JSON.stringify(options))); } getCompletionEntrySymbol(): ts.Symbol { throw new Error("getCompletionEntrySymbol not implemented across the shim layer."); diff --git a/src/server/client.ts b/src/server/client.ts index d08d1e13d2e66..39e30848e3e52 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -198,7 +198,9 @@ namespace ts.server { const request = this.processRequest(CommandNames.CompletionDetails, args); const response = this.processResponse(request); Debug.assert(response.body.length === 1, "Unexpected length of completion details response body."); - return response.body[0]; + + const convertedCodeActions = map(response.body[0].codeActions, codeAction => this.convertCodeActions(codeAction, fileName)); + return { ...response.body[0], codeActions: convertedCodeActions }; } getCompletionEntrySymbol(_fileName: string, _position: number, _entryName: string): Symbol { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 3d07392bbe69f..7b9e9fe80969a 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1658,6 +1658,11 @@ namespace ts.server.protocol { * this span should be used instead of the default one. */ replacementSpan?: TextSpan; + /** + * Indicates whether commiting this completion entry will require additional code actions to be + * made to avoid errors. The CompletionEntryDetails will have these actions. + */ + hasAction?: true; } /** @@ -1690,6 +1695,11 @@ namespace ts.server.protocol { * JSDoc tags for the symbol. */ tags: JSDocTagInfo[]; + + /** + * The associated code actions for this entry + */ + codeActions?: CodeAction[]; } export interface CompletionsResponse extends Response { diff --git a/src/server/session.ts b/src/server/session.ts index 800d09ff6c283..d10daecc92d1e 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1178,11 +1178,12 @@ namespace ts.server { const completions = project.getLanguageService().getCompletionsAtPosition(file, position); if (simplifiedResult) { - return mapDefined(completions && completions.entries, entry => { + return mapDefined(completions && completions.entries, entry => { if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) { - const { name, kind, kindModifiers, sortText, replacementSpan } = entry; + const { name, kind, kindModifiers, sortText, replacementSpan, hasAction } = entry; const convertedSpan = replacementSpan ? this.decorateSpan(replacementSpan, scriptInfo) : undefined; - return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan }; + // Use `hasAction || undefined` to avoid serializing `false`. + return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan, hasAction: hasAction || undefined }; } }).sort((a, b) => compareStrings(a.name, b.name)); } @@ -1193,10 +1194,20 @@ namespace ts.server { private getCompletionEntryDetails(args: protocol.CompletionDetailsRequestArgs): ReadonlyArray { const { file, project } = this.getFileAndProject(args); - const position = this.getPositionInFile(args, file); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); + const position = this.getPosition(args, scriptInfo); + const formattingOptions = project.projectService.getFormatCodeOptions(file); - return mapDefined(args.entryNames, entryName => - project.getLanguageService().getCompletionEntryDetails(file, position, entryName)); + return mapDefined(args.entryNames, entryName => { + const details = project.getLanguageService().getCompletionEntryDetails(file, position, entryName, formattingOptions); + if (details) { + const mappedCodeActions = map(details.codeActions, action => this.mapCodeAction(action, scriptInfo)); + return { ...details, codeActions: mappedCodeActions }; + } + else { + return undefined; + } + }); } private getCompileOnSaveAffectedFileList(args: protocol.FileRequestArgs): ReadonlyArray { diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 13e11ed4674f3..ad9ab520dabcf 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -5,15 +5,13 @@ namespace ts { getCodeActions(context: CodeFixContext): CodeAction[] | undefined; } - export interface CodeFixContext { + export interface CodeFixContext extends textChanges.TextChangesContext { errorCode: number; sourceFile: SourceFile; span: TextSpan; program: Program; - newLineCharacter: string; host: LanguageServiceHost; cancellationToken: CancellationToken; - rulesProvider: formatting.RulesProvider; } export namespace codefix { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 9b54543231dd4..3e4e0f9e82246 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -1,5 +1,7 @@ /* @internal */ namespace ts.codefix { + import ChangeTracker = textChanges.ChangeTracker; + registerCodeFix({ errorCodes: [ Diagnostics.Cannot_find_name_0.code, @@ -11,11 +13,35 @@ namespace ts.codefix { }); type ImportCodeActionKind = "CodeChange" | "InsertingIntoExistingImport" | "NewImport"; + // Map from module Id to an array of import declarations in that module. + type ImportDeclarationMap = AnyImportSyntax[][]; + interface ImportCodeAction extends CodeAction { kind: ImportCodeActionKind; moduleSpecifier?: string; } + interface SymbolContext extends textChanges.TextChangesContext { + sourceFile: SourceFile; + symbolName: string; + } + + interface SymbolAndTokenContext extends SymbolContext { + symbolToken: Node | undefined; + } + + interface ImportCodeFixContext extends SymbolAndTokenContext { + host: LanguageServiceHost; + checker: TypeChecker; + compilerOptions: CompilerOptions; + getCanonicalFileName(fileName: string): string; + cachedImportDeclarations?: ImportDeclarationMap; + } + + export interface ImportCodeFixOptions extends ImportCodeFixContext { + kind: ImportKind; + } + const enum ModuleSpecifierComparison { Better, Equal, @@ -118,561 +144,550 @@ namespace ts.codefix { } } - function getImportCodeActions(context: CodeFixContext): ImportCodeAction[] { - const sourceFile = context.sourceFile; - const checker = context.program.getTypeChecker(); - const allSourceFiles = context.program.getSourceFiles(); + function createCodeAction( + description: DiagnosticMessage, + diagnosticArgs: string[], + changes: FileTextChanges[], + kind: ImportCodeActionKind, + moduleSpecifier: string | undefined, + ): ImportCodeAction { + return { + description: formatMessage.apply(undefined, [undefined, description].concat(diagnosticArgs)), + changes, + kind, + moduleSpecifier + }; + } + + function convertToImportCodeFixContext(context: CodeFixContext): ImportCodeFixContext { const useCaseSensitiveFileNames = context.host.useCaseSensitiveFileNames ? context.host.useCaseSensitiveFileNames() : false; + const checker = context.program.getTypeChecker(); + const symbolToken = getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false); + return { + host: context.host, + newLineCharacter: context.newLineCharacter, + rulesProvider: context.rulesProvider, + sourceFile: context.sourceFile, + checker, + compilerOptions: context.program.getCompilerOptions(), + cachedImportDeclarations: [], + getCanonicalFileName: createGetCanonicalFileName(useCaseSensitiveFileNames), + symbolName: symbolToken.getText(), + symbolToken, + }; + } - const token = getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); - const name = token.getText(); - const symbolIdActionMap = new ImportCodeActionMap(); + export const enum ImportKind { + Named, + Default, + Namespace, + } - // this is a module id -> module import declaration map - const cachedImportDeclarations: AnyImportSyntax[][] = []; - let lastImportDeclaration: Node; - - const currentTokenMeaning = getMeaningFromLocation(token); - if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) { - const umdSymbol = checker.getSymbolAtLocation(token); - let symbol: ts.Symbol; - let symbolName: string; - if (umdSymbol.flags & ts.SymbolFlags.Alias) { - symbol = checker.getAliasedSymbol(umdSymbol); - symbolName = name; - } - else if (isJsxOpeningLikeElement(token.parent) && token.parent.tagName === token) { - // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. - symbol = checker.getAliasedSymbol(checker.resolveName(checker.getJsxNamespace(), token.parent.tagName, SymbolFlags.Value)); - symbolName = symbol.name; - } - else { - Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); + export function getCodeActionForImport(moduleSymbol: Symbol, context: ImportCodeFixOptions): ImportCodeAction[] { + const declarations = getImportDeclarations(moduleSymbol, context.checker, context.sourceFile, context.cachedImportDeclarations); + const actions: ImportCodeAction[] = []; + if (context.symbolToken) { + // It is possible that multiple import statements with the same specifier exist in the file. + // e.g. + // + // import * as ns from "foo"; + // import { member1, member2 } from "foo"; + // + // member3/**/ <-- cusor here + // + // in this case we should provie 2 actions: + // 1. change "member3" to "ns.member3" + // 2. add "member3" to the second import statement's import list + // and it is up to the user to decide which one fits best. + for (const declaration of declarations) { + const namespace = getNamespaceImportName(declaration); + if (namespace) { + actions.push(getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken)); + } } + } + actions.push(getCodeActionForAddImport(moduleSymbol, context, declarations)); + return actions; + } - return getCodeActionForImport(symbol, symbolName, /*isDefault*/ false, /*isNamespaceImport*/ true); + function getNamespaceImportName(declaration: AnyImportSyntax): Identifier { + if (declaration.kind === SyntaxKind.ImportDeclaration) { + const namedBindings = declaration.importClause && declaration.importClause.namedBindings; + return namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport ? namedBindings.name : undefined; + } + else { + return declaration.name; } + } - const candidateModules = checker.getAmbientModules(); - for (const otherSourceFile of allSourceFiles) { - if (otherSourceFile !== sourceFile && isExternalOrCommonJsModule(otherSourceFile)) { - candidateModules.push(otherSourceFile.symbol); - } + // TODO(anhans): This doesn't seem important to cache... just use an iterator instead of creating a new array? + function getImportDeclarations(moduleSymbol: Symbol, checker: TypeChecker, { imports }: SourceFile, cachedImportDeclarations: ImportDeclarationMap = []): ReadonlyArray { + const moduleSymbolId = getUniqueSymbolId(moduleSymbol, checker); + let cached = cachedImportDeclarations[moduleSymbolId]; + if (!cached) { + cached = cachedImportDeclarations[moduleSymbolId] = mapDefined(imports, importModuleSpecifier => + checker.getSymbolAtLocation(importModuleSpecifier) === moduleSymbol ? getImportDeclaration(importModuleSpecifier) : undefined); } + return cached; + } - for (const moduleSymbol of candidateModules) { - context.cancellationToken.throwIfCancellationRequested(); + function getImportDeclaration({ parent }: LiteralExpression): AnyImportSyntax | undefined { + switch (parent.kind) { + case SyntaxKind.ImportDeclaration: + return parent as ImportDeclaration; + case SyntaxKind.ExternalModuleReference: + return (parent as ExternalModuleReference).parent; + default: + Debug.assert(parent.kind === SyntaxKind.ExportDeclaration); + // Ignore these, can't add imports to them. + return undefined; + } + } - // check the default export - const defaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol); - if (defaultExport) { - const localSymbol = getLocalSymbolForExportDefault(defaultExport); - if (localSymbol && localSymbol.escapedName === name && checkSymbolHasMeaning(localSymbol, currentTokenMeaning)) { - // check if this symbol is already used - const symbolId = getUniqueSymbolId(localSymbol); - symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name, /*isNamespaceImport*/ true)); - } + function getCodeActionForNewImport(context: SymbolContext & { kind: ImportKind }, moduleSpecifier: string): ImportCodeAction { + const { kind, sourceFile, newLineCharacter, symbolName } = context; + const lastImportDeclaration = findLast(sourceFile.statements, isAnyImportSyntax); + + const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier); + const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClauseOfKind(kind, symbolName), createStringLiteralWithQuoteStyle(sourceFile, moduleSpecifierWithoutQuotes)); + const changes = ChangeTracker.with(context, changeTracker => { + if (lastImportDeclaration) { + changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: newLineCharacter }); } + else { + changeTracker.insertNodeAt(sourceFile, getSourceFileImportLocation(sourceFile), importDecl, { suffix: `${newLineCharacter}${newLineCharacter}` }); + } + }); + + // if this file doesn't have any import statements, insert an import statement and then insert a new line + // between the only import statement and user code. Otherwise just insert the statement because chances + // are there are already a new line seperating code and import statements. + return createCodeAction( + Diagnostics.Import_0_from_1, + [symbolName, moduleSpecifierWithoutQuotes], + changes, + "NewImport", + moduleSpecifierWithoutQuotes, + ); + } - // "default" is a keyword and not a legal identifier for the import, so we don't expect it here - Debug.assert(name !== "default"); + function createStringLiteralWithQuoteStyle(sourceFile: SourceFile, text: string): StringLiteral { + const literal = createLiteral(text); + const firstModuleSpecifier = firstOrUndefined(sourceFile.imports); + literal.singleQuote = !!firstModuleSpecifier && !isStringDoubleQuoted(firstModuleSpecifier, sourceFile); + return literal; + } - // check exports with the same name - const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(name, moduleSymbol); - if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { - const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName); - symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name)); - } + function createImportClauseOfKind(kind: ImportKind, symbolName: string) { + switch (kind) { + case ImportKind.Default: + return createImportClause(createIdentifier(symbolName), /*namedBindings*/ undefined); + case ImportKind.Namespace: + return createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(symbolName))); + case ImportKind.Named: + return createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(symbolName))])); + default: + Debug.assertNever(kind); } + } - return symbolIdActionMap.getAllActions(); - - function getImportDeclarations(moduleSymbol: Symbol) { - const moduleSymbolId = getUniqueSymbolId(moduleSymbol); + function getModuleSpecifierForNewImport(sourceFile: SourceFile, moduleSymbol: Symbol, options: CompilerOptions, getCanonicalFileName: (file: string) => string, host: LanguageServiceHost): string | undefined { + const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().fileName; + const sourceDirectory = getDirectoryPath(sourceFile.fileName); - const cached = cachedImportDeclarations[moduleSymbolId]; - if (cached) { - return cached; - } + return tryGetModuleNameFromAmbientModule(moduleSymbol) || + tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName) || + tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) || + tryGetModuleNameFromBaseUrl(options, moduleFileName, getCanonicalFileName) || + options.rootDirs && tryGetModuleNameFromRootDirs(options.rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName) || + removeFileExtension(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName)); + } - const existingDeclarations = mapDefined(sourceFile.imports, importModuleSpecifier => - checker.getSymbolAtLocation(importModuleSpecifier) === moduleSymbol ? getImportDeclaration(importModuleSpecifier) : undefined); - cachedImportDeclarations[moduleSymbolId] = existingDeclarations; - return existingDeclarations; - - function getImportDeclaration({ parent }: LiteralExpression): AnyImportSyntax { - switch (parent.kind) { - case SyntaxKind.ImportDeclaration: - return parent as ImportDeclaration; - case SyntaxKind.ExternalModuleReference: - return (parent as ExternalModuleReference).parent; - default: - return undefined; - } - } + function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol): string | undefined { + const decl = moduleSymbol.valueDeclaration; + if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) { + return decl.name.text; } + } - function getUniqueSymbolId(symbol: Symbol) { - return getSymbolId(skipAlias(symbol, checker)); + function tryGetModuleNameFromBaseUrl(options: CompilerOptions, moduleFileName: string, getCanonicalFileName: (file: string) => string): string | undefined { + if (!options.baseUrl) { + return undefined; } - function checkSymbolHasMeaning(symbol: Symbol, meaning: SemanticMeaning) { - const declarations = symbol.getDeclarations(); - return declarations ? some(symbol.declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning)) : false; + let relativeName = getRelativePathIfInDirectory(moduleFileName, options.baseUrl, getCanonicalFileName); + if (!relativeName) { + return undefined; } - function getCodeActionForImport(moduleSymbol: Symbol, symbolName: string, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] { - const existingDeclarations = getImportDeclarations(moduleSymbol); - if (existingDeclarations.length > 0) { - // With an existing import statement, there are more than one actions the user can do. - return getCodeActionsForExistingImport(existingDeclarations); - } - else { - return [getCodeActionForNewImport()]; - } + const relativeNameWithIndex = removeFileExtension(relativeName); + relativeName = removeExtensionAndIndexPostFix(relativeName); - function getCodeActionsForExistingImport(declarations: (ImportDeclaration | ImportEqualsDeclaration)[]): ImportCodeAction[] { - const actions: ImportCodeAction[] = []; - - // It is possible that multiple import statements with the same specifier exist in the file. - // e.g. - // - // import * as ns from "foo"; - // import { member1, member2 } from "foo"; - // - // member3/**/ <-- cusor here - // - // in this case we should provie 2 actions: - // 1. change "member3" to "ns.member3" - // 2. add "member3" to the second import statement's import list - // and it is up to the user to decide which one fits best. - let namespaceImportDeclaration: ImportDeclaration | ImportEqualsDeclaration; - let namedImportDeclaration: ImportDeclaration; - let existingModuleSpecifier: string; - for (const declaration of declarations) { - if (declaration.kind === SyntaxKind.ImportDeclaration) { - const namedBindings = declaration.importClause && declaration.importClause.namedBindings; - if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { - // case: - // import * as ns from "foo" - namespaceImportDeclaration = declaration; - } - else { - // cases: - // import default from "foo" - // import { bar } from "foo" or combination with the first one - // import "foo" - namedImportDeclaration = declaration; + if (options.paths) { + for (const key in options.paths) { + for (const pattern of options.paths[key]) { + const indexOfStar = pattern.indexOf("*"); + if (indexOfStar === 0 && pattern.length === 1) { + continue; + } + else if (indexOfStar !== -1) { + const prefix = pattern.substr(0, indexOfStar); + const suffix = pattern.substr(indexOfStar + 1); + if (relativeName.length >= prefix.length + suffix.length && + startsWith(relativeName, prefix) && + endsWith(relativeName, suffix)) { + const matchedStar = relativeName.substr(prefix.length, relativeName.length - suffix.length); + return key.replace("\*", matchedStar); } - existingModuleSpecifier = declaration.moduleSpecifier.getText(); } - else { - // case: - // import foo = require("foo") - namespaceImportDeclaration = declaration; - existingModuleSpecifier = getModuleSpecifierFromImportEqualsDeclaration(declaration); + else if (pattern === relativeName || pattern === relativeNameWithIndex) { + return key; } } + } + } - if (namespaceImportDeclaration) { - actions.push(getCodeActionForNamespaceImport(namespaceImportDeclaration)); - } - - if (!isNamespaceImport && namedImportDeclaration && namedImportDeclaration.importClause && - (namedImportDeclaration.importClause.name || namedImportDeclaration.importClause.namedBindings)) { - /** - * If the existing import declaration already has a named import list, just - * insert the identifier into that list. - */ - const fileTextChanges = getTextChangeForImportClause(namedImportDeclaration.importClause); - const moduleSpecifierWithoutQuotes = stripQuotes(namedImportDeclaration.moduleSpecifier.getText()); - actions.push(createCodeAction( - Diagnostics.Add_0_to_existing_import_declaration_from_1, - [name, moduleSpecifierWithoutQuotes], - fileTextChanges, - "InsertingIntoExistingImport", - moduleSpecifierWithoutQuotes - )); - } - else { - // we need to create a new import statement, but the existing module specifier can be reused. - actions.push(getCodeActionForNewImport(existingModuleSpecifier)); - } - return actions; - - function getModuleSpecifierFromImportEqualsDeclaration(declaration: ImportEqualsDeclaration) { - if (declaration.moduleReference && declaration.moduleReference.kind === SyntaxKind.ExternalModuleReference) { - return declaration.moduleReference.expression.getText(); - } - return declaration.moduleReference.getText(); - } + return relativeName; + } - function getTextChangeForImportClause(importClause: ImportClause): FileTextChanges[] { - const importList = importClause.namedBindings; - const newImportSpecifier = createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name)); - // case 1: - // original text: import default from "module" - // change to: import default, { name } from "module" - // case 2: - // original text: import {} from "module" - // change to: import { name } from "module" - if (!importList || importList.elements.length === 0) { - const newImportClause = createImportClause(importClause.name, createNamedImports([newImportSpecifier])); - return createChangeTracker().replaceNode(sourceFile, importClause, newImportClause).getChanges(); - } + function tryGetModuleNameFromRootDirs(rootDirs: ReadonlyArray, moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string): string | undefined { + const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName); + if (normalizedTargetPath === undefined) { + return undefined; + } - /** - * If the import list has one import per line, preserve that. Otherwise, insert on same line as last element - * import { - * foo - * } from "./module"; - */ - return createChangeTracker().insertNodeInListAfter( - sourceFile, - importList.elements[importList.elements.length - 1], - newImportSpecifier).getChanges(); - } + const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName); + const relativePath = normalizedSourcePath !== undefined ? getRelativePath(normalizedTargetPath, normalizedSourcePath, getCanonicalFileName) : normalizedTargetPath; + return removeFileExtension(relativePath); + } - function getCodeActionForNamespaceImport(declaration: ImportDeclaration | ImportEqualsDeclaration): ImportCodeAction { - let namespacePrefix: string; - if (declaration.kind === SyntaxKind.ImportDeclaration) { - namespacePrefix = (declaration.importClause.namedBindings).name.getText(); - } - else { - namespacePrefix = declaration.name.getText(); - } - namespacePrefix = stripQuotes(namespacePrefix); - - /** - * Cases: - * import * as ns from "mod" - * import default, * as ns from "mod" - * import ns = require("mod") - * - * Because there is no import list, we alter the reference to include the - * namespace instead of altering the import declaration. For example, "foo" would - * become "ns.foo" - */ - return createCodeAction( - Diagnostics.Change_0_to_1, - [name, `${namespacePrefix}.${name}`], - createChangeTracker().replaceNode(sourceFile, token, createPropertyAccess(createIdentifier(namespacePrefix), name)).getChanges(), - "CodeChange" - ); - } + function tryGetModuleNameFromTypeRoots( + options: CompilerOptions, + host: GetEffectiveTypeRootsHost, + getCanonicalFileName: (file: string) => string, + moduleFileName: string, + ): string | undefined { + return firstDefined(getEffectiveTypeRoots(options, host), unNormalizedTypeRoot => { + const typeRoot = toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName); + if (startsWith(moduleFileName, typeRoot)) { + return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1)); } + }); + } - function getCodeActionForNewImport(moduleSpecifier?: string): ImportCodeAction { - if (!lastImportDeclaration) { - // insert after any existing imports - for (let i = sourceFile.statements.length - 1; i >= 0; i--) { - const statement = sourceFile.statements[i]; - if (statement.kind === SyntaxKind.ImportEqualsDeclaration || statement.kind === SyntaxKind.ImportDeclaration) { - lastImportDeclaration = statement; - break; - } - } - } + function tryGetModuleNameAsNodeModule( + options: CompilerOptions, + moduleFileName: string, + host: LanguageServiceHost, + getCanonicalFileName: (file: string) => string, + sourceDirectory: string, + ): string | undefined { + if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) { + // nothing to do here + return undefined; + } - const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); - const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport()); - const changeTracker = createChangeTracker(); - const importClause = isDefault - ? createImportClause(createIdentifier(symbolName), /*namedBindings*/ undefined) - : isNamespaceImport - ? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(symbolName))) - : createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(symbolName))])); - const moduleSpecifierLiteral = createLiteral(moduleSpecifierWithoutQuotes); - moduleSpecifierLiteral.singleQuote = getSingleQuoteStyleFromExistingImports(); - const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, moduleSpecifierLiteral); - if (!lastImportDeclaration) { - changeTracker.insertNodeAt(sourceFile, getSourceFileImportLocation(sourceFile), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` }); - } - else { - changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: context.newLineCharacter }); - } + const parts = getNodeModulePathParts(moduleFileName); - // if this file doesn't have any import statements, insert an import statement and then insert a new line - // between the only import statement and user code. Otherwise just insert the statement because chances - // are there are already a new line seperating code and import statements. - return createCodeAction( - Diagnostics.Import_0_from_1, - [symbolName, `"${moduleSpecifierWithoutQuotes}"`], - changeTracker.getChanges(), - "NewImport", - moduleSpecifierWithoutQuotes - ); - - function getSingleQuoteStyleFromExistingImports() { - const firstModuleSpecifier = forEach(sourceFile.statements, node => { - if (isImportDeclaration(node) || isExportDeclaration(node)) { - if (node.moduleSpecifier && isStringLiteral(node.moduleSpecifier)) { - return node.moduleSpecifier; - } - } - else if (isImportEqualsDeclaration(node)) { - if (isExternalModuleReference(node.moduleReference) && isStringLiteral(node.moduleReference.expression)) { - return node.moduleReference.expression; - } + if (!parts) { + return undefined; + } + + // Simplify the full file path to something that can be resolved by Node. + + // If the module could be imported by a directory name, use that directory's name + let moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName); + // Get a path that's relative to node_modules or the importing file's path + moduleSpecifier = getNodeResolvablePath(moduleSpecifier); + // If the module was found in @types, get the actual Node package name + return getPackageNameFromAtTypesDirectory(moduleSpecifier); + + function getDirectoryOrExtensionlessFileName(path: string): string { + // If the file is the main module, it can be imported by the package name + const packageRootPath = path.substring(0, parts.packageRootIndex); + const packageJsonPath = combinePaths(packageRootPath, "package.json"); + if (host.fileExists(packageJsonPath)) { + const packageJsonContent = JSON.parse(host.readFile(packageJsonPath)); + if (packageJsonContent) { + const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; + if (mainFileRelative) { + const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); + if (mainExportFile === getCanonicalFileName(path)) { + return packageRootPath; } - }); - if (firstModuleSpecifier) { - return sourceFile.text.charCodeAt(firstModuleSpecifier.getStart()) === CharacterCodes.singleQuote; } } + } - function getModuleSpecifierForNewImport() { - const fileName = sourceFile.fileName; - const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().fileName; - const sourceDirectory = getDirectoryPath(fileName); - const options = context.program.getCompilerOptions(); - - return tryGetModuleNameFromAmbientModule() || - tryGetModuleNameFromTypeRoots() || - tryGetModuleNameAsNodeModule() || - tryGetModuleNameFromBaseUrl() || - tryGetModuleNameFromRootDirs() || - removeFileExtension(getRelativePath(moduleFileName, sourceDirectory)); - - function tryGetModuleNameFromAmbientModule(): string { - const decl = moduleSymbol.valueDeclaration; - if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) { - return decl.name.text; - } - } + // We still have a file name - remove the extension + const fullModulePathWithoutExtension = removeFileExtension(path); - function tryGetModuleNameFromBaseUrl() { - if (!options.baseUrl) { - return undefined; - } + // If the file is /index, it can be imported by its directory name + if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index") { + return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex); + } - let relativeName = getRelativePathIfInDirectory(moduleFileName, options.baseUrl); - if (!relativeName) { - return undefined; - } + return fullModulePathWithoutExtension; + } - const relativeNameWithIndex = removeFileExtension(relativeName); - relativeName = removeExtensionAndIndexPostFix(relativeName); - - if (options.paths) { - for (const key in options.paths) { - for (const pattern of options.paths[key]) { - const indexOfStar = pattern.indexOf("*"); - if (indexOfStar === 0 && pattern.length === 1) { - continue; - } - else if (indexOfStar !== -1) { - const prefix = pattern.substr(0, indexOfStar); - const suffix = pattern.substr(indexOfStar + 1); - if (relativeName.length >= prefix.length + suffix.length && - startsWith(relativeName, prefix) && - endsWith(relativeName, suffix)) { - const matchedStar = relativeName.substr(prefix.length, relativeName.length - suffix.length); - return key.replace("\*", matchedStar); - } - } - else if (pattern === relativeName || pattern === relativeNameWithIndex) { - return key; - } - } - } - } + function getNodeResolvablePath(path: string): string { + const basePath = path.substring(0, parts.topLevelNodeModulesIndex); + if (sourceDirectory.indexOf(basePath) === 0) { + // if node_modules folder is in this folder or any of its parent folders, no need to keep it. + return path.substring(parts.topLevelPackageNameIndex + 1); + } + else { + return getRelativePath(path, sourceDirectory, getCanonicalFileName); + } + } + } - return relativeName; - } + function getNodeModulePathParts(fullPath: string) { + // If fullPath can't be valid module file within node_modules, returns undefined. + // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js + // Returns indices: ^ ^ ^ ^ + + let topLevelNodeModulesIndex = 0; + let topLevelPackageNameIndex = 0; + let packageRootIndex = 0; + let fileNameIndex = 0; + + const enum States { + BeforeNodeModules, + NodeModules, + Scope, + PackageContent + } - function tryGetModuleNameFromRootDirs() { - if (options.rootDirs) { - const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, options.rootDirs); - const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, options.rootDirs); - if (normalizedTargetPath !== undefined) { - const relativePath = normalizedSourcePath !== undefined ? getRelativePath(normalizedTargetPath, normalizedSourcePath) : normalizedTargetPath; - return removeFileExtension(relativePath); - } - } - return undefined; + let partStart = 0; + let partEnd = 0; + let state = States.BeforeNodeModules; + + while (partEnd >= 0) { + partStart = partEnd; + partEnd = fullPath.indexOf("/", partStart + 1); + switch (state) { + case States.BeforeNodeModules: + if (fullPath.indexOf("/node_modules/", partStart) === partStart) { + topLevelNodeModulesIndex = partStart; + topLevelPackageNameIndex = partEnd; + state = States.NodeModules; } - - function tryGetModuleNameFromTypeRoots() { - const typeRoots = getEffectiveTypeRoots(options, context.host); - if (typeRoots) { - const normalizedTypeRoots = map(typeRoots, typeRoot => toPath(typeRoot, /*basePath*/ undefined, getCanonicalFileName)); - for (const typeRoot of normalizedTypeRoots) { - if (startsWith(moduleFileName, typeRoot)) { - const relativeFileName = moduleFileName.substring(typeRoot.length + 1); - return removeExtensionAndIndexPostFix(relativeFileName); - } - } - } + break; + case States.NodeModules: + case States.Scope: + if (state === States.NodeModules && fullPath.charAt(partStart + 1) === "@") { + state = States.Scope; } + else { + packageRootIndex = partEnd; + state = States.PackageContent; + } + break; + case States.PackageContent: + if (fullPath.indexOf("/node_modules/", partStart) === partStart) { + state = States.NodeModules; + } + else { + state = States.PackageContent; + } + break; + } + } - function tryGetModuleNameAsNodeModule() { - if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) { - // nothing to do here - return undefined; - } - - const parts = getNodeModulePathParts(moduleFileName); - - if (!parts) { - return undefined; - } + fileNameIndex = partStart; - // Simplify the full file path to something that can be resolved by Node. - - // If the module could be imported by a directory name, use that directory's name - let moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName); - // Get a path that's relative to node_modules or the importing file's path - moduleSpecifier = getNodeResolvablePath(moduleSpecifier); - // If the module was found in @types, get the actual Node package name - return getPackageNameFromAtTypesDirectory(moduleSpecifier); - - function getDirectoryOrExtensionlessFileName(path: string): string { - // If the file is the main module, it can be imported by the package name - const packageRootPath = path.substring(0, parts.packageRootIndex); - const packageJsonPath = combinePaths(packageRootPath, "package.json"); - if (context.host.fileExists(packageJsonPath)) { - const packageJsonContent = JSON.parse(context.host.readFile(packageJsonPath)); - if (packageJsonContent) { - const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; - if (mainFileRelative) { - const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); - if (mainExportFile === getCanonicalFileName(path)) { - return packageRootPath; - } - } - } - } - - // We still have a file name - remove the extension - const fullModulePathWithoutExtension = removeFileExtension(path); - - // If the file is /index, it can be imported by its directory name - if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index") { - return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex); - } - - return fullModulePathWithoutExtension; - } + return state > States.NodeModules ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : undefined; + } - function getNodeResolvablePath(path: string): string { - const basePath = path.substring(0, parts.topLevelNodeModulesIndex); - if (sourceDirectory.indexOf(basePath) === 0) { - // if node_modules folder is in this folder or any of its parent folders, no need to keep it. - return path.substring(parts.topLevelPackageNameIndex + 1); - } - else { - return getRelativePath(path, sourceDirectory); - } - } - } - } + function getPathRelativeToRootDirs(path: string, rootDirs: ReadonlyArray, getCanonicalFileName: (fileName: string) => string): string | undefined { + return firstDefined(rootDirs, rootDir => getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName)); + } - function getNodeModulePathParts(fullPath: string) { - // If fullPath can't be valid module file within node_modules, returns undefined. - // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js - // Returns indices: ^ ^ ^ ^ - - let topLevelNodeModulesIndex = 0; - let topLevelPackageNameIndex = 0; - let packageRootIndex = 0; - let fileNameIndex = 0; - - const enum States { - BeforeNodeModules, - NodeModules, - Scope, - PackageContent - } + function removeExtensionAndIndexPostFix(fileName: string) { + fileName = removeFileExtension(fileName); + if (endsWith(fileName, "/index")) { + fileName = fileName.substr(0, fileName.length - 6/* "/index".length */); + } + return fileName; + } - let partStart = 0; - let partEnd = 0; - let state = States.BeforeNodeModules; - - while (partEnd >= 0) { - partStart = partEnd; - partEnd = fullPath.indexOf("/", partStart + 1); - switch (state) { - case States.BeforeNodeModules: - if (fullPath.indexOf("/node_modules/", partStart) === partStart) { - topLevelNodeModulesIndex = partStart; - topLevelPackageNameIndex = partEnd; - state = States.NodeModules; - } - break; - case States.NodeModules: - case States.Scope: - if (state === States.NodeModules && fullPath.charAt(partStart + 1) === "@") { - state = States.Scope; - } - else { - packageRootIndex = partEnd; - state = States.PackageContent; - } - break; - case States.PackageContent: - if (fullPath.indexOf("/node_modules/", partStart) === partStart) { - state = States.NodeModules; - } - else { - state = States.PackageContent; - } - break; - } - } + function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: (fileName: string) => string): string | undefined { + const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + return isRootedDiskPath(relativePath) || startsWith(relativePath, "..") ? undefined : relativePath; + } - fileNameIndex = partStart; + function getRelativePath(path: string, directoryPath: string, getCanonicalFileName: (fileName: string) => string) { + const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + return !pathIsRelative(relativePath) ? "./" + relativePath : relativePath; + } - return state > States.NodeModules ? { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex, fileNameIndex } : undefined; + function getCodeActionForAddImport( + moduleSymbol: Symbol, + ctx: ImportCodeFixOptions, + declarations: ReadonlyArray): ImportCodeAction { + const fromExistingImport = firstDefined(declarations, declaration => { + if (declaration.kind === SyntaxKind.ImportDeclaration && declaration.importClause) { + const changes = tryUpdateExistingImport(ctx, ctx.kind, declaration.importClause); + if (changes) { + const moduleSpecifierWithoutQuotes = stripQuotes(declaration.moduleSpecifier.getText()); + return createCodeAction( + Diagnostics.Add_0_to_existing_import_declaration_from_1, + [ctx.symbolName, moduleSpecifierWithoutQuotes], + changes, + "InsertingIntoExistingImport", + moduleSpecifierWithoutQuotes); } + } + }); + if (fromExistingImport) { + return fromExistingImport; + } - function getPathRelativeToRootDirs(path: string, rootDirs: string[]) { - for (const rootDir of rootDirs) { - const relativeName = getRelativePathIfInDirectory(path, rootDir); - if (relativeName !== undefined) { - return relativeName; - } - } - return undefined; - } + const moduleSpecifier = firstDefined(declarations, moduleSpecifierFromAnyImport) + || getModuleSpecifierForNewImport(ctx.sourceFile, moduleSymbol, ctx.compilerOptions, ctx.getCanonicalFileName, ctx.host); + return getCodeActionForNewImport(ctx, moduleSpecifier); + } - function removeExtensionAndIndexPostFix(fileName: string) { - fileName = removeFileExtension(fileName); - if (endsWith(fileName, "/index")) { - fileName = fileName.substr(0, fileName.length - 6/* "/index".length */); - } - return fileName; - } + function moduleSpecifierFromAnyImport(node: AnyImportSyntax): string | undefined { + const expression = node.kind === SyntaxKind.ImportDeclaration + ? node.moduleSpecifier + : node.moduleReference.kind === SyntaxKind.ExternalModuleReference + ? node.moduleReference.expression + : undefined; + return expression && isStringLiteral(expression) ? expression.text : undefined; + } - function getRelativePathIfInDirectory(path: string, directoryPath: string) { - const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); - return isRootedDiskPath(relativePath) || startsWith(relativePath, "..") ? undefined : relativePath; + function tryUpdateExistingImport(context: SymbolContext, kind: ImportKind, importClause: ImportClause): FileTextChanges[] | undefined { + const { symbolName, sourceFile } = context; + const { name, namedBindings } = importClause; + switch (kind) { + case ImportKind.Default: + return name ? undefined : ChangeTracker.with(context, t => + t.replaceNode(sourceFile, importClause, createImportClause(createIdentifier(symbolName), namedBindings))); + + case ImportKind.Named: { + const newImportSpecifier = createImportSpecifier(/*propertyName*/ undefined, createIdentifier(symbolName)); + if (namedBindings && namedBindings.kind === SyntaxKind.NamedImports && namedBindings.elements.length !== 0) { + // There are already named imports; add another. + return ChangeTracker.with(context, t => t.insertNodeInListAfter( + sourceFile, + namedBindings.elements[namedBindings.elements.length - 1], + newImportSpecifier)); } - - function getRelativePath(path: string, directoryPath: string) { - const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); - return !pathIsRelative(relativePath) ? "./" + relativePath : relativePath; + if (!namedBindings || namedBindings.kind === SyntaxKind.NamedImports && namedBindings.elements.length === 0) { + return ChangeTracker.with(context, t => + t.replaceNode(sourceFile, importClause, createImportClause(name, createNamedImports([newImportSpecifier])))); } + return undefined; } + case ImportKind.Namespace: + return namedBindings ? undefined : ChangeTracker.with(context, t => + t.replaceNode(sourceFile, importClause, createImportClause(name, createNamespaceImport(createIdentifier(symbolName))))); + + default: + Debug.assertNever(kind); } + } + + function getCodeActionForUseExistingNamespaceImport(namespacePrefix: string, context: SymbolContext, symbolToken: Node): ImportCodeAction { + const { symbolName, sourceFile } = context; + + /** + * Cases: + * import * as ns from "mod" + * import default, * as ns from "mod" + * import ns = require("mod") + * + * Because there is no import list, we alter the reference to include the + * namespace instead of altering the import declaration. For example, "foo" would + * become "ns.foo" + */ + return createCodeAction( + Diagnostics.Change_0_to_1, + [symbolName, `${namespacePrefix}.${symbolName}`], + ChangeTracker.with(context, tracker => + tracker.replaceNode(sourceFile, symbolToken, createPropertyAccess(createIdentifier(namespacePrefix), symbolName))), + "CodeChange", + /*moduleSpecifier*/ undefined); + } + + function getImportCodeActions(context: CodeFixContext): ImportCodeAction[] { + const importFixContext = convertToImportCodeFixContext(context); + return context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code + ? getActionsForUMDImport(importFixContext) + : getActionsForNonUMDImport(importFixContext, context.program.getSourceFiles(), context.cancellationToken); + } - function createChangeTracker() { - return textChanges.ChangeTracker.fromContext(context); + function getActionsForUMDImport(context: ImportCodeFixContext): ImportCodeAction[] { + const { checker, symbolToken } = context; + const umdSymbol = checker.getSymbolAtLocation(symbolToken); + let symbol: ts.Symbol; + let symbolName: string; + if (umdSymbol.flags & ts.SymbolFlags.Alias) { + symbol = checker.getAliasedSymbol(umdSymbol); + symbolName = context.symbolName; } + else if (isJsxOpeningLikeElement(symbolToken.parent) && symbolToken.parent.tagName === symbolToken) { + // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. + symbol = checker.getAliasedSymbol(checker.resolveName(checker.getJsxNamespace(), symbolToken.parent.tagName, SymbolFlags.Value)); + symbolName = symbol.name; + } + else { + Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); + } + + return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Namespace }); + } + + function getActionsForNonUMDImport(context: ImportCodeFixContext, allSourceFiles: ReadonlyArray, cancellationToken: CancellationToken): ImportCodeAction[] { + const { sourceFile, checker, symbolName, symbolToken } = context; + // "default" is a keyword and not a legal identifier for the import, so we don't expect it here + Debug.assert(symbolName !== "default"); + const symbolIdActionMap = new ImportCodeActionMap(); + const currentTokenMeaning = getMeaningFromLocation(symbolToken); + + forEachExternalModule(checker, allSourceFiles, moduleSymbol => { + if (moduleSymbol === sourceFile.symbol) { + return; + } + + cancellationToken.throwIfCancellationRequested(); + // check the default export + const defaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol); + if (defaultExport) { + const localSymbol = getLocalSymbolForExportDefault(defaultExport); + if (localSymbol && localSymbol.escapedName === symbolName && checkSymbolHasMeaning(localSymbol, currentTokenMeaning)) { + // check if this symbol is already used + const symbolId = getUniqueSymbolId(localSymbol, checker); + symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, { ...context, kind: ImportKind.Default })); + } + } - function createCodeAction( - description: DiagnosticMessage, - diagnosticArgs: string[], - changes: FileTextChanges[], - kind: ImportCodeActionKind, - moduleSpecifier?: string): ImportCodeAction { - return { - description: formatMessage.apply(undefined, [undefined, description].concat(diagnosticArgs)), - changes, - kind, - moduleSpecifier - }; + // check exports with the same name + const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); + if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { + const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName, checker); + symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, { ...context, kind: ImportKind.Named })); + } + }); + + return symbolIdActionMap.getAllActions(); + } + + function checkSymbolHasMeaning({ declarations }: Symbol, meaning: SemanticMeaning): boolean { + return some(declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning)); + } + + export function forEachExternalModule(checker: TypeChecker, allSourceFiles: ReadonlyArray, cb: (module: Symbol) => void) { + for (const ambient of checker.getAmbientModules()) { + cb(ambient); + } + for (const sourceFile of allSourceFiles) { + if (isExternalOrCommonJsModule(sourceFile)) { + cb(sourceFile.symbol); + } } } } diff --git a/src/services/completions.ts b/src/services/completions.ts index c222425693709..7afa85ce26df4 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -4,13 +4,31 @@ namespace ts.Completions { export type Log = (message: string) => void; + interface SymbolOriginInfo { + moduleSymbol: Symbol; + isDefaultExport: boolean; + } + /** + * Map from symbol id -> SymbolOriginInfo. + * Only populated for symbols that come from other modules. + */ + type SymbolOriginInfoMap = SymbolOriginInfo[]; + const enum KeywordCompletionFilters { None, ClassElementKeywords, // Keywords at class keyword ConstructorParameterKeywords, // Keywords at constructor parameter } - export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: Log, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined { + export function getCompletionsAtPosition( + host: LanguageServiceHost, + typeChecker: TypeChecker, + log: Log, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, + position: number, + allSourceFiles: ReadonlyArray, + ): CompletionInfo | undefined { if (isInReferenceComment(sourceFile, position)) { return PathCompletions.getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host); } @@ -19,12 +37,12 @@ namespace ts.Completions { return getStringLiteralCompletionEntries(sourceFile, position, typeChecker, compilerOptions, host, log); } - const completionData = getCompletionData(typeChecker, log, sourceFile, position); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles); if (!completionData) { return undefined; } - const { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, request, keywordFilters } = completionData; + const { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, request, keywordFilters, symbolToOriginInfoMap } = completionData; if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) { @@ -56,7 +74,7 @@ namespace ts.Completions { const entries: CompletionEntry[] = []; if (isSourceFileJavaScript(sourceFile)) { - const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral); + const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral, symbolToOriginInfoMap); getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); } else { @@ -64,7 +82,7 @@ namespace ts.Completions { return undefined; } - getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral); + getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true, typeChecker, compilerOptions.target, log, allowStringLiteral, symbolToOriginInfoMap); } // TODO add filter for keyword based on type/value/namespace and also location @@ -134,7 +152,17 @@ namespace ts.Completions { }; } - function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: Push, location: Node, performCharacterChecks: boolean, typeChecker: TypeChecker, target: ScriptTarget, log: Log, allowStringLiteral: boolean): Map { + function getCompletionEntriesFromSymbols( + symbols: ReadonlyArray, + entries: Push, + location: Node, + performCharacterChecks: boolean, + typeChecker: TypeChecker, + target: ScriptTarget, + log: Log, + allowStringLiteral: boolean, + symbolToOriginInfoMap?: SymbolOriginInfoMap, + ): Map { const start = timestamp(); const uniqueNames = createMap(); if (symbols) { @@ -143,6 +171,9 @@ namespace ts.Completions { if (entry) { const id = entry.name; if (!uniqueNames.has(id)) { + if (symbolToOriginInfoMap && symbolToOriginInfoMap[getUniqueSymbolId(symbol, typeChecker)]) { + entry.hasAction = true; + } entries.push(entry); uniqueNames.set(id, true); } @@ -298,53 +329,89 @@ namespace ts.Completions { } } - export function getCompletionEntryDetails(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): CompletionEntryDetails { + export function getCompletionEntryDetails( + typeChecker: TypeChecker, + log: (message: string) => void, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, + position: number, + name: string, + allSourceFiles: ReadonlyArray, + host: LanguageServiceHost, + rulesProvider: formatting.RulesProvider, + ): CompletionEntryDetails { + // Compute all the completion symbols again. - const completionData = getCompletionData(typeChecker, log, sourceFile, position); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles); if (completionData) { - const { symbols, location, allowStringLiteral } = completionData; + const { symbols, location, allowStringLiteral, symbolToOriginInfoMap } = completionData; // Find the symbol with the matching entry name. // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral) === entryName ? s : undefined); + const symbol = find(symbols, s => getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral) === name); if (symbol) { + const codeActions = getCompletionEntryCodeActions(symbolToOriginInfoMap, symbol, typeChecker, host, compilerOptions, sourceFile, rulesProvider); + const kindModifiers = SymbolDisplay.getSymbolModifiers(symbol); const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location, SemanticMeaning.All); - return { - name: entryName, - kindModifiers: SymbolDisplay.getSymbolModifiers(symbol), - kind: symbolKind, - displayParts, - documentation, - tags - }; + return { name, kindModifiers, kind: symbolKind, displayParts, documentation, tags, codeActions }; } } // Didn't find a symbol with this name. See if we can find a keyword instead. const keywordCompletion = forEach( getKeywordCompletions(KeywordCompletionFilters.None), - c => c.name === entryName + c => c.name === name ); if (keywordCompletion) { return { - name: entryName, + name, kind: ScriptElementKind.keyword, kindModifiers: ScriptElementKindModifier.none, - displayParts: [displayPart(entryName, SymbolDisplayPartKind.keyword)], + displayParts: [displayPart(name, SymbolDisplayPartKind.keyword)], documentation: undefined, - tags: undefined + tags: undefined, + codeActions: undefined, }; } return undefined; } - export function getCompletionEntrySymbol(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): Symbol | undefined { + function getCompletionEntryCodeActions(symbolToOriginInfoMap: SymbolOriginInfoMap, symbol: Symbol, checker: TypeChecker, host: LanguageServiceHost, compilerOptions: CompilerOptions, sourceFile: SourceFile, rulesProvider: formatting.RulesProvider): CodeAction[] | undefined { + const symbolOriginInfo = symbolToOriginInfoMap[getUniqueSymbolId(symbol, checker)]; + if (!symbolOriginInfo) { + return undefined; + } + + const { moduleSymbol, isDefaultExport } = symbolOriginInfo; + return codefix.getCodeActionForImport(moduleSymbol, { + host, + checker, + newLineCharacter: host.getNewLine(), + compilerOptions, + sourceFile, + rulesProvider, + symbolName: symbol.name, + getCanonicalFileName: createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false), + symbolToken: undefined, + kind: isDefaultExport ? codefix.ImportKind.Default : codefix.ImportKind.Named, + }); + } + + export function getCompletionEntrySymbol( + typeChecker: TypeChecker, + log: (message: string) => void, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, + position: number, + entryName: string, + allSourceFiles: ReadonlyArray, + ): Symbol | undefined { // Compute all the completion symbols again. - const completionData = getCompletionData(typeChecker, log, sourceFile, position); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles); if (!completionData) { return undefined; } @@ -353,7 +420,7 @@ namespace ts.Completions { // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - return forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral) === entryName ? s : undefined); + return find(symbols, s => getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral) === entryName); } interface CompletionData { @@ -366,10 +433,17 @@ namespace ts.Completions { isRightOfDot: boolean; request?: Request; keywordFilters: KeywordCompletionFilters; + symbolToOriginInfoMap: SymbolOriginInfoMap; } type Request = { kind: "JsDocTagName" } | { kind: "JsDocTag" } | { kind: "JsDocParameterName", tag: JSDocParameterTag }; - function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number): CompletionData | undefined { + function getCompletionData( + typeChecker: TypeChecker, + log: (message: string) => void, + sourceFile: SourceFile, + position: number, + allSourceFiles: ReadonlyArray, + ): CompletionData | undefined { const isJavaScriptFile = isSourceFileJavaScript(sourceFile); let request: Request | undefined; @@ -441,7 +515,18 @@ namespace ts.Completions { } if (request) { - return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, allowStringLiteral: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, request, keywordFilters: KeywordCompletionFilters.None }; + return { + symbols: undefined, + isGlobalCompletion: false, + isMemberCompletion: false, + allowStringLiteral: false, + isNewIdentifierLocation: false, + location: undefined, + isRightOfDot: false, + request, + keywordFilters: KeywordCompletionFilters.None, + symbolToOriginInfoMap: undefined, + }; } if (!insideJsDocTagTypeExpression) { @@ -543,6 +628,7 @@ namespace ts.Completions { let isNewIdentifierLocation: boolean; let keywordFilters = KeywordCompletionFilters.None; let symbols: Symbol[] = []; + const symbolToOriginInfoMap: SymbolOriginInfoMap = []; if (isRightOfDot) { getTypeScriptMemberSymbols(); @@ -579,7 +665,7 @@ namespace ts.Completions { log("getCompletionData: Semantic work: " + (timestamp() - semanticStart)); - return { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, keywordFilters }; + return { symbols, isGlobalCompletion, isMemberCompletion, allowStringLiteral, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, keywordFilters, symbolToOriginInfoMap }; type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; @@ -752,13 +838,16 @@ namespace ts.Completions { } const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; - symbols = filterGlobalCompletion(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings)); + + symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); + getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : ""); + filterGlobalCompletion(symbols); return true; } - function filterGlobalCompletion(symbols: Symbol[]) { - return filter(symbols, symbol => { + function filterGlobalCompletion(symbols: Symbol[]): void { + filterMutate(symbols, symbol => { if (!isSourceFile(location)) { // export = /**/ here we want to get all meanings, so any symbol is ok if (isExportAssignment(location.parent)) { @@ -832,6 +921,59 @@ namespace ts.Completions { } } + function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string): void { + const tokenTextLowerCase = tokenText.toLowerCase(); + const symbolIdMap = arrayToNumericMap(symbols, s => getUniqueSymbolId(s, typeChecker)); + + codefix.forEachExternalModule(typeChecker, allSourceFiles, moduleSymbol => { + if (moduleSymbol === sourceFile.symbol) { + return; + } + + for (let symbol of typeChecker.getExportsOfModule(moduleSymbol)) { + let { name } = symbol; + const isDefaultExport = name === "default"; + if (isDefaultExport) { + const localSymbol = getLocalSymbolForExportDefault(symbol); + if (localSymbol) { + symbol = localSymbol; + name = localSymbol.name; + } + } + + const id = getUniqueSymbolId(symbol, typeChecker); + if (!symbolIdMap[id] && stringContainsCharactersInOrder(name.toLowerCase(), tokenTextLowerCase)) { + symbols.push(symbol); + symbolToOriginInfoMap[id] = { moduleSymbol, isDefaultExport }; + } + } + }); + } + + /** + * True if you could remove some characters in `a` to get `b`. + * E.g., true for "abcdef" and "bdf". + * But not true for "abcdef" and "dbf". + */ + function stringContainsCharactersInOrder(str: string, characters: string): boolean { + if (characters.length === 0) { + return true; + } + + let characterIndex = 0; + for (let strIndex = 0; strIndex < str.length; strIndex++) { + if (str.charCodeAt(strIndex) === characters.charCodeAt(characterIndex)) { + characterIndex++; + if (characterIndex === characters.length) { + return true; + } + } + } + + // Did not find all characters + return false; + } + /** * Finds the first node that "embraces" the position, so that one may * accurately aggregate locals from the closest containing scope. @@ -1627,7 +1769,7 @@ namespace ts.Completions { // First check of the displayName is not external module; if it is an external module, it is not valid entry if (symbol.flags & SymbolFlags.Namespace) { const firstCharCode = name.charCodeAt(0); - if (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote) { + if (isSingleOrDoubleQuote(firstCharCode)) { // If the symbol is external module, don't show it in the completion list // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) return undefined; diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index e3bf9deac8932..780b14db719f2 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -339,7 +339,7 @@ namespace ts.Completions.PathCompletions { } } else if (host.getDirectories) { - let typeRoots: string[]; + let typeRoots: ReadonlyArray; try { // Wrap in try catch because getEffectiveTypeRoots touches the filesystem typeRoots = getEffectiveTypeRoots(options, host); diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index e956a4121c791..b338882e6db68 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -14,13 +14,11 @@ namespace ts { getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined; } - export interface RefactorContext { + export interface RefactorContext extends textChanges.TextChangesContext { file: SourceFile; startPosition: number; endPosition?: number; program: Program; - newLineCharacter: string; - rulesProvider?: formatting.RulesProvider; cancellationToken?: CancellationToken; } diff --git a/src/services/services.ts b/src/services/services.ts index 6bdc96d8b4d65..0399ca1658e9d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1324,17 +1324,19 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - return Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position); + return Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, program.getSourceFiles()); } - function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails { + function getCompletionEntryDetails(fileName: string, position: number, entryName: string, formattingOptions?: FormatCodeSettings): CompletionEntryDetails { synchronizeHostData(); - return Completions.getCompletionEntryDetails(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + const ruleProvider = formattingOptions ? getRuleProvider(formattingOptions) : undefined; + return Completions.getCompletionEntryDetails( + program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName, program.getSourceFiles(), host, ruleProvider); } function getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol { synchronizeHostData(); - return Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + return Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName, program.getSourceFiles()); } function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { diff --git a/src/services/shims.ts b/src/services/shims.ts index 9d4baccc3c4e0..c9f5c4c2fb23c 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -141,7 +141,7 @@ namespace ts { getEncodedSemanticClassifications(fileName: string, start: number, length: number): string; getCompletionsAtPosition(fileName: string, position: number): string; - getCompletionEntryDetails(fileName: string, position: number, entryName: string): string; + getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: string/*Services.FormatCodeOptions*/): string; getQuickInfoAtPosition(fileName: string, position: number): string; @@ -893,10 +893,13 @@ namespace ts { } /** Get a string based representation of a completion list entry details */ - public getCompletionEntryDetails(fileName: string, position: number, entryName: string) { + public getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: string/*Services.FormatCodeOptions*/) { return this.forwardJSONCall( `getCompletionEntryDetails('${fileName}', ${position}, '${entryName}')`, - () => this.languageService.getCompletionEntryDetails(fileName, position, entryName) + () => { + const localOptions: ts.FormatCodeOptions = JSON.parse(options); + return this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions); + } ); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 9e4c2ed3a6003..63cfa64ef07b9 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -186,14 +186,25 @@ namespace ts.textChanges { return s; } + export interface TextChangesContext { + newLineCharacter: string; + rulesProvider: formatting.RulesProvider; + } + export class ChangeTracker { private changes: Change[] = []; private readonly newLineCharacter: string; - public static fromContext(context: RefactorContext | CodeFixContext) { + public static fromContext(context: TextChangesContext): ChangeTracker { return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.rulesProvider); } + public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] { + const tracker = ChangeTracker.fromContext(context); + cb(tracker); + return tracker.getChanges(); + } + constructor( private readonly newLine: NewLineKind, private readonly rulesProvider: formatting.RulesProvider, diff --git a/src/services/types.ts b/src/services/types.ts index e853eb7b96cad..7bf4a909a7a34 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -230,7 +230,8 @@ namespace ts { getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; - getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; + // "options" is optional only for backwards-compatibility + getCompletionEntryDetails(fileName: string, position: number, entryName: string, options?: FormatCodeOptions | FormatCodeSettings): CompletionEntryDetails; getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; @@ -668,6 +669,7 @@ namespace ts { * be used in that case */ replacementSpan?: TextSpan; + hasAction?: true; } export interface CompletionEntryDetails { @@ -677,6 +679,7 @@ namespace ts { displayParts: SymbolDisplayPart[]; documentation: SymbolDisplayPart[]; tags: JSDocTagInfo[]; + codeActions?: CodeAction[]; } export interface OutliningSpan { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index ffeb5e70eed42..716a4188db25b 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1281,9 +1281,7 @@ namespace ts { */ export function stripQuotes(name: string) { const length = name.length; - if (length >= 2 && - name.charCodeAt(0) === name.charCodeAt(length - 1) && - (name.charCodeAt(0) === CharacterCodes.doubleQuote || name.charCodeAt(0) === CharacterCodes.singleQuote)) { + if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && isSingleOrDoubleQuote(name.charCodeAt(0))) { return name.substring(1, length - 1); } return name; @@ -1300,6 +1298,10 @@ namespace ts { return ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } + export function getUniqueSymbolId(symbol: Symbol, checker: TypeChecker) { + return getSymbolId(skipAlias(symbol, checker)); + } + export function getFirstNonSpaceCharacterPosition(text: string, position: number) { while (isWhiteSpaceLike(text.charCodeAt(position))) { position += 1; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e983ac73b1551..56c7fa5f98c44 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3207,10 +3207,11 @@ declare namespace ts { }; } declare namespace ts { - function getEffectiveTypeRoots(options: CompilerOptions, host: { - directoryExists?: (directoryName: string) => boolean; - getCurrentDirectory?: () => string; - }): string[] | undefined; + interface GetEffectiveTypeRootsHost { + directoryExists?(directoryName: string): boolean; + getCurrentDirectory?(): string; + } + function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; /** * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups @@ -3913,7 +3914,7 @@ declare namespace ts { getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; - getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; + getCompletionEntryDetails(fileName: string, position: number, entryName: string, options?: FormatCodeOptions | FormatCodeSettings): CompletionEntryDetails; getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; @@ -4281,6 +4282,7 @@ declare namespace ts { * be used in that case */ replacementSpan?: TextSpan; + hasAction?: true; } interface CompletionEntryDetails { name: string; @@ -4289,6 +4291,7 @@ declare namespace ts { displayParts: SymbolDisplayPart[]; documentation: SymbolDisplayPart[]; tags: JSDocTagInfo[]; + codeActions?: CodeAction[]; } interface OutliningSpan { /** The span of the document to actually collapse. */ @@ -6038,6 +6041,11 @@ declare namespace ts.server.protocol { * this span should be used instead of the default one. */ replacementSpan?: TextSpan; + /** + * Indicates whether commiting this completion entry will require additional code actions to be + * made to avoid errors. The CompletionEntryDetails will have these actions. + */ + hasAction?: true; } /** * Additional completion entry details, available on demand @@ -6067,6 +6075,10 @@ declare namespace ts.server.protocol { * JSDoc tags for the symbol. */ tags: JSDocTagInfo[]; + /** + * The associated code actions for this entry + */ + codeActions?: CodeAction[]; } interface CompletionsResponse extends Response { body?: CompletionEntry[]; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 14fae7d0d77a0..2668a25bcfcd2 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3154,10 +3154,11 @@ declare namespace ts { function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; } declare namespace ts { - function getEffectiveTypeRoots(options: CompilerOptions, host: { - directoryExists?: (directoryName: string) => boolean; - getCurrentDirectory?: () => string; - }): string[] | undefined; + interface GetEffectiveTypeRootsHost { + directoryExists?(directoryName: string): boolean; + getCurrentDirectory?(): string; + } + function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; /** * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups @@ -3913,7 +3914,7 @@ declare namespace ts { getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; - getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; + getCompletionEntryDetails(fileName: string, position: number, entryName: string, options?: FormatCodeOptions | FormatCodeSettings): CompletionEntryDetails; getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; @@ -4281,6 +4282,7 @@ declare namespace ts { * be used in that case */ replacementSpan?: TextSpan; + hasAction?: true; } interface CompletionEntryDetails { name: string; @@ -4289,6 +4291,7 @@ declare namespace ts { displayParts: SymbolDisplayPart[]; documentation: SymbolDisplayPart[]; tags: JSDocTagInfo[]; + codeActions?: CodeAction[]; } interface OutliningSpan { /** The span of the document to actually collapse. */ diff --git a/tests/cases/fourslash/completionsImport_default_addToNamedImports.ts b/tests/cases/fourslash/completionsImport_default_addToNamedImports.ts new file mode 100644 index 0000000000000..5662b57fdf678 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_default_addToNamedImports.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /a.ts +////export default function foo() {} +////export const x = 0; + +// @Filename: /b.ts +////import { x } from "./a"; +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Add 'foo' to existing import declaration from "./a".`, + newFileContent: `import foo, { x } from "./a"; +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_default_addToNamespaceImport.ts b/tests/cases/fourslash/completionsImport_default_addToNamespaceImport.ts new file mode 100644 index 0000000000000..b442ed21549e1 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_default_addToNamespaceImport.ts @@ -0,0 +1,18 @@ +/// + +// @Filename: /a.ts +////export default function foo() {} + +// @Filename: /b.ts +////import * as a from "./a"; +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Add 'foo' to existing import declaration from "./a".`, + newFileContent: `import foo, * as a from "./a"; +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts b/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts new file mode 100644 index 0000000000000..3ee4decb0f8b7 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts @@ -0,0 +1,20 @@ +/// + +// @Filename: /a.ts +////export default function foo() {} + +// @Filename: /b.ts +////import f_o_o from "./a"; +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Import 'foo' from "./a".`, + // TODO: GH#18445 + newFileContent: `import f_o_o from "./a"; +import foo from "./a";\r +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts b/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts new file mode 100644 index 0000000000000..6dbd437d36470 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /a.ts +////export default function foo() {} + +// @Filename: /b.ts +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Import 'foo' from "./a".`, + // TODO: GH#18445 + newFileContent: `import foo from "./a";\r +\r +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_fromAmbientModule.ts b/tests/cases/fourslash/completionsImport_fromAmbientModule.ts new file mode 100644 index 0000000000000..b45ad9824865a --- /dev/null +++ b/tests/cases/fourslash/completionsImport_fromAmbientModule.ts @@ -0,0 +1,18 @@ +/// + +// @Filename: /a.ts +////declare module "m" { +//// export const x: number; +////} + +// @Filename: /b.ts +/////**/ + +verify.applyCodeActionFromCompletion("", { + name: "x", + description: `Import 'x' from "m".`, + // TODO: GH#18445 + newFileContent: `import { x } from "m";\r +\r +`, +}); diff --git a/tests/cases/fourslash/completionsImport_matching.ts b/tests/cases/fourslash/completionsImport_matching.ts new file mode 100644 index 0000000000000..3470d59bff20b --- /dev/null +++ b/tests/cases/fourslash/completionsImport_matching.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: /a.ts +// Not included: +////export function abcde() {} +////export function dbf() {} +// Included: +////export function bdf() {} +////export function abcdef() {} +////export function BDF() {} + +// @Filename: /b.ts +////bdf/**/ + +goTo.marker(""); + +verify.not.completionListContains("abcde"); +verify.not.completionListContains("dbf"); + +verify.completionListContains("bdf", "function bdf(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); +verify.completionListContains("abcdef", "function abcdef(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); +verify.completionListContains("BDF", "function BDF(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); diff --git a/tests/cases/fourslash/completionsImport_named_addToNamedImports.ts b/tests/cases/fourslash/completionsImport_named_addToNamedImports.ts new file mode 100644 index 0000000000000..23119ad491f79 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_named_addToNamedImports.ts @@ -0,0 +1,19 @@ +/// + +// @Filename: /a.ts +////export function foo() {} +////export const x = 0; + +// @Filename: /b.ts +////import { x } from "./a"; +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Add 'foo' to existing import declaration from "./a".`, + newFileContent: `import { x, foo } from "./a"; +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_named_didNotExistBefore.ts b/tests/cases/fourslash/completionsImport_named_didNotExistBefore.ts new file mode 100644 index 0000000000000..95c68c2a05e88 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_named_didNotExistBefore.ts @@ -0,0 +1,20 @@ +/// + +// @Filename: /a.ts +////export function Test1() {} +////export function Test2() {} + +// @Filename: /b.ts +////import { Test2 } from "./a"; +////t/**/ + +goTo.marker(""); +verify.completionListContains("Test1", "function Test1(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); +verify.completionListContains("Test2", "import Test2", "", "alias", /*spanIndex*/ undefined, /*hasAction*/ undefined); + +verify.applyCodeActionFromCompletion("", { + name: "Test1", + description: `Add 'Test1' to existing import declaration from "./a".`, + newFileContent: `import { Test2, Test1 } from "./a"; +t`, +}); diff --git a/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts b/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts new file mode 100644 index 0000000000000..da00907e60fb7 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts @@ -0,0 +1,20 @@ +/// + +// @Filename: /a.ts +////export function foo() {} + +// @Filename: /b.ts +////import * as a from "./a"; +////f/**/; + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); + +verify.applyCodeActionFromCompletion("", { + name: "foo", + description: `Import 'foo' from "./a".`, + // TODO: GH#18445 + newFileContent: `import * as a from "./a"; +import { foo } from "./a";\r +f;`, +}); diff --git a/tests/cases/fourslash/completionsImport_previousTokenIsSemicolon.ts b/tests/cases/fourslash/completionsImport_previousTokenIsSemicolon.ts new file mode 100644 index 0000000000000..904de35354ac5 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_previousTokenIsSemicolon.ts @@ -0,0 +1,11 @@ +/// + +// @Filename: /a.ts +////export function foo() {} + +// @Filename: /b.ts +////import * as a from 'a'; +/////**/ + +goTo.marker(""); +verify.completionListContains("foo", "function foo(): void", "", "function", /*spanIndex*/ undefined, /*hasAction*/ true); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index f4d47abc9c9c4..e1d9607de8aaf 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -140,7 +140,14 @@ declare namespace FourSlashInterface { allowedConstructorParameterKeywords: string[]; constructor(negative?: boolean); completionListCount(expectedCount: number): void; - completionListContains(symbol: string, text?: string, documentation?: string, kind?: string, spanIndex?: number): void; + completionListContains( + symbol: string, + text?: string, + documentation?: string, + kind?: string, + spanIndex?: number, + hasAction?: boolean, + ): void; completionListItemsCountIsGreaterThan(count: number): void; completionListIsEmpty(): void; completionListContainsClassElementKeywords(): void; @@ -173,6 +180,20 @@ declare namespace FourSlashInterface { assertHasRanges(ranges: Range[]): void; caretAtMarker(markerName?: string): void; completionsAt(markerName: string, completions: string[], options?: { isNewIdentifierLocation?: boolean }): void; + completionsAndDetailsAt( + markerName: string, + completions: { + excludes?: ReadonlyArray, + //TODO: better type + entries: ReadonlyArray<{ entry: any, details: any }>, + }, + ): void; //TODO: better type + applyCodeActionFromCompletion(markerName: string, options: { + name: string, + description: string, + newFileContent?: string, + newRangeContent?: string, + }); indentationIs(numberOfSpaces: number): void; indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: ts.IndentStyle, baseIndentSize?: number): void; textAtCaretIs(text: string): void; diff --git a/tests/cases/fourslash/importNameCodeFixOptionalImport0.ts b/tests/cases/fourslash/importNameCodeFixOptionalImport0.ts index 34cebad941544..218ec4fabb724 100644 --- a/tests/cases/fourslash/importNameCodeFixOptionalImport0.ts +++ b/tests/cases/fourslash/importNameCodeFixOptionalImport0.ts @@ -8,7 +8,7 @@ //// export function foo() {}; // @Filename: a/foo.ts -//// export { foo } from "./foo/bar"; +//// export { foo } from "./foo/bar"; verify.importFixAtPosition([ `import * as ns from "./foo"; From f09fe3d0eca877fe4282d860114dd4cf0a476958 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Oct 2017 10:45:48 -0700 Subject: [PATCH 194/246] Dont try to run unit tests with rwc tests again (#19240) --- src/harness/parallel/host.ts | 2 +- src/harness/runner.ts | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index d7bba70408e7f..bf218c1b3a127 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -137,7 +137,7 @@ namespace Harness.Parallel.Host { let closedWorkers = 0; for (let i = 0; i < workerCount; i++) { // TODO: Just send the config over the IPC channel or in the command line arguments - const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: runners.length !== 1 }; + const config: TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests }; const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`); Harness.IO.writeFile(configPath, JSON.stringify(config)); const child = fork(__filename, [`--config="${configPath}"`]); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index c1345f422c394..db807b976bb18 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -82,7 +82,7 @@ let testConfigContent = let taskConfigsFolder: string; let workerCount: number; -let runUnitTests = true; +let runUnitTests: boolean | undefined; let noColors = false; interface TestConfig { @@ -108,9 +108,7 @@ function handleTestConfig() { if (testConfig.light) { Harness.lightMode = true; } - if (testConfig.runUnitTests !== undefined) { - runUnitTests = testConfig.runUnitTests; - } + runUnitTests = testConfig.runUnitTests; if (testConfig.workerCount) { workerCount = +testConfig.workerCount; } @@ -199,6 +197,9 @@ function handleTestConfig() { runners.push(new FourSlashRunner(FourSlashTestType.Server)); // runners.push(new GeneratedFourslashRunner()); } + if (runUnitTests === undefined) { + runUnitTests = runners.length !== 1; // Don't run unit tests when running only one runner if unit tests were not explicitly asked for + } } function beginTests() { From d0c4d13fe2a836e76ffadd6dd7b6328e1cc056e9 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Oct 2017 11:34:59 -0700 Subject: [PATCH 195/246] In tsserver, indent logged JSON (#19080) --- src/server/server.ts | 8 ++++---- src/server/session.ts | 10 +++++----- src/server/typingsInstaller/nodeTypingsInstaller.ts | 2 +- src/server/utilities.ts | 11 +++++++++++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index f24251ee6ac90..17905ece33ade 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -350,14 +350,14 @@ namespace ts.server { const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); if (this.logger.hasLevel(LogLevel.verbose)) { if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Scheduling throttled operation: ${JSON.stringify(request)}`); + this.logger.info(`Scheduling throttled operation:${stringifyIndented(request)}`); } } const operationId = project.getProjectName(); const operation = () => { if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Sending request: ${JSON.stringify(request)}`); + this.logger.info(`Sending request:${stringifyIndented(request)}`); } this.installer.send(request); }; @@ -377,7 +377,7 @@ namespace ts.server { private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`Received response: ${JSON.stringify(response)}`); + this.logger.info(`Received response:${stringifyIndented(response)}`); } switch (response.kind) { @@ -780,7 +780,7 @@ namespace ts.server { try { const args = [combinePaths(__dirname, "watchGuard.js"), path]; if (logger.hasLevel(LogLevel.verbose)) { - logger.info(`Starting ${process.execPath} with args ${JSON.stringify(args)}`); + logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); } childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { "ELECTRON_RUN_AS_NODE": "1" } }); status = true; diff --git a/src/server/session.ts b/src/server/session.ts index d10daecc92d1e..017784530d5bf 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -131,7 +131,7 @@ namespace ts.server { const json = JSON.stringify(msg); if (verboseLogging) { - logger.info(msg.type + ": " + json); + logger.info(msg.type + ":\n" + indent(json)); } const len = byteLength(json, "utf8"); @@ -383,9 +383,9 @@ namespace ts.server { public logError(err: Error, cmd: string) { let msg = "Exception on executing command " + cmd; if (err.message) { - msg += ":\n" + err.message; + msg += ":\n" + indent(err.message); if ((err).stack) { - msg += "\n" + (err).stack; + msg += "\n" + indent((err).stack); } } this.logger.msg(msg, Msg.Err); @@ -1962,7 +1962,7 @@ namespace ts.server { return this.executeWithRequestId(request.seq, () => handler(request)); } else { - this.logger.msg(`Unrecognized JSON command: ${JSON.stringify(request)}`, Msg.Err); + this.logger.msg(`Unrecognized JSON command:${stringifyIndented(request)}`, Msg.Err); this.output(undefined, CommandNames.Unknown, request.seq, `Unrecognized JSON command: ${request.command}`); return { responseRequired: false }; } @@ -1974,7 +1974,7 @@ namespace ts.server { if (this.logger.hasLevel(LogLevel.requestTime)) { start = this.hrtime(); if (this.logger.hasLevel(LogLevel.verbose)) { - this.logger.info(`request: ${message}`); + this.logger.info(`request:${indent(message)}`); } } diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 98478c2d5fc39..d32dd2a4b5f76 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -145,7 +145,7 @@ namespace ts.server.typingsInstaller { protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { if (this.log.isEnabled()) { - this.log.writeLine(`Sending response: ${JSON.stringify(response)}`); + this.log.writeLine(`Sending response:\n ${JSON.stringify(response)}`); } process.send(response); if (this.log.isEnabled()) { diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 6832e7ba34714..69399b672b35d 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -318,4 +318,15 @@ namespace ts.server { deleted(oldItems[oldIndex++]); } } + + /* @internal */ + export function indent(string: string): string { + return "\n " + string; + } + + /** Put stringified JSON on the next line, indented. */ + /* @internal */ + export function stringifyIndented(json: {}): string { + return "\n " + JSON.stringify(json); + } } From 28509e1732f7861119b3c368a46a845143aafd03 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Oct 2017 11:57:47 -0700 Subject: [PATCH 196/246] noUnusedLocals: Warn for recursive call to private method (#18920) --- src/compiler/checker.ts | 15 +++++++-- .../noUnusedLocals_selfReference.errors.txt | 12 ++++--- .../reference/noUnusedLocals_selfReference.js | 22 ++++++------- .../noUnusedLocals_selfReference.symbols | 31 +++++++++---------- .../noUnusedLocals_selfReference.types | 21 ++++++------- .../compiler/noUnusedLocals_selfReference.ts | 7 ++--- 6 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2aff217fc624e..219f370fd53f5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15028,7 +15028,7 @@ namespace ts { checkPropertyNotUsedBeforeDeclaration(prop, node, right); - markPropertyAsReferenced(prop, node); + markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword); getNodeLinks(node).resolvedSymbol = prop; @@ -15218,12 +15218,21 @@ namespace ts { return bestCandidate; } - function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined) { + function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isThisAccess: boolean) { if (prop && noUnusedIdentifiers && (prop.flags & SymbolFlags.ClassMember) && prop.valueDeclaration && hasModifier(prop.valueDeclaration, ModifierFlags.Private) && !(nodeForCheckWriteOnly && isWriteOnlyAccess(nodeForCheckWriteOnly))) { + + if (isThisAccess) { + // Find any FunctionLikeDeclaration because those create a new 'this' binding. But this should only matter for methods (or getters/setters). + const containingMethod = findAncestor(nodeForCheckWriteOnly, isFunctionLikeDeclaration); + if (containingMethod && containingMethod.symbol === prop) { + return; + } + } + if (getCheckFlags(prop) & CheckFlags.Instantiated) { getSymbolLinks(prop).target.isReferenced = true; } @@ -20716,7 +20725,7 @@ namespace ts { const parentType = getTypeForBindingElementParent(parent); const name = node.propertyName || node.name; const property = getPropertyOfType(parentType, getTextOfPropertyName(name)); - markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined); // A destructuring is never a write-only reference. + markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. if (parent.initializer && property) { checkPropertyAccessibility(parent, parent.initializer, parentType, property); } diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt index 603bc54d4481a..e1d198ff5590b 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt +++ b/tests/baselines/reference/noUnusedLocals_selfReference.errors.txt @@ -2,9 +2,10 @@ tests/cases/compiler/noUnusedLocals_selfReference.ts(3,10): error TS6133: 'f' is tests/cases/compiler/noUnusedLocals_selfReference.ts(5,14): error TS6133: 'g' is declared but its value is never read. tests/cases/compiler/noUnusedLocals_selfReference.ts(9,7): error TS6133: 'C' is declared but its value is never read. tests/cases/compiler/noUnusedLocals_selfReference.ts(12,6): error TS6133: 'E' is declared but its value is never read. +tests/cases/compiler/noUnusedLocals_selfReference.ts(14,19): error TS6133: 'm' is declared but its value is never read. -==== tests/cases/compiler/noUnusedLocals_selfReference.ts (4 errors) ==== +==== tests/cases/compiler/noUnusedLocals_selfReference.ts (5 errors) ==== export {}; // Make this a module scope, so these are local variables. function f() { @@ -26,11 +27,12 @@ tests/cases/compiler/noUnusedLocals_selfReference.ts(12,6): error TS6133: 'E' is ~ !!! error TS6133: 'E' is declared but its value is never read. + class P { private m() { this.m; } } + ~ +!!! error TS6133: 'm' is declared but its value is never read. + P; + // Does not detect mutual recursion. function g() { D; } class D { m() { g; } } - - // Does not work on private methods. - class P { private m() { this.m; } } - P; \ No newline at end of file diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.js b/tests/baselines/reference/noUnusedLocals_selfReference.js index a8f3d6a8aedf6..c23d829534080 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.js +++ b/tests/baselines/reference/noUnusedLocals_selfReference.js @@ -12,13 +12,12 @@ class C { } enum E { A = 0, B = E.A } +class P { private m() { this.m; } } +P; + // Does not detect mutual recursion. function g() { D; } class D { m() { g; } } - -// Does not work on private methods. -class P { private m() { this.m; } } -P; //// [noUnusedLocals_selfReference.js] @@ -41,6 +40,13 @@ var E; E[E["A"] = 0] = "A"; E[E["B"] = 0] = "B"; })(E || (E = {})); +var P = /** @class */ (function () { + function P() { + } + P.prototype.m = function () { this.m; }; + return P; +}()); +P; // Does not detect mutual recursion. function g() { D; } var D = /** @class */ (function () { @@ -49,11 +55,3 @@ var D = /** @class */ (function () { D.prototype.m = function () { g; }; return D; }()); -// Does not work on private methods. -var P = /** @class */ (function () { - function P() { - } - P.prototype.m = function () { this.m; }; - return P; -}()); -P; diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.symbols b/tests/baselines/reference/noUnusedLocals_selfReference.symbols index 015a78d87d3f5..cd4195094fed4 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.symbols +++ b/tests/baselines/reference/noUnusedLocals_selfReference.symbols @@ -29,24 +29,23 @@ enum E { A = 0, B = E.A } >E : Symbol(E, Decl(noUnusedLocals_selfReference.ts, 10, 1)) >A : Symbol(E.A, Decl(noUnusedLocals_selfReference.ts, 11, 8)) +class P { private m() { this.m; } } +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 11, 25)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) +>this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) +>this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 11, 25)) +>m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 13, 9)) + +P; +>P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 11, 25)) + // Does not detect mutual recursion. function g() { D; } ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 14, 2)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 17, 19)) class D { m() { g; } } ->D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 14, 19)) ->m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 15, 9)) ->g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 11, 25)) - -// Does not work on private methods. -class P { private m() { this.m; } } ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) ->this.m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) ->this : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) ->m : Symbol(P.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) - -P; ->P : Symbol(P, Decl(noUnusedLocals_selfReference.ts, 15, 22)) +>D : Symbol(D, Decl(noUnusedLocals_selfReference.ts, 17, 19)) +>m : Symbol(D.m, Decl(noUnusedLocals_selfReference.ts, 18, 9)) +>g : Symbol(g, Decl(noUnusedLocals_selfReference.ts, 14, 2)) diff --git a/tests/baselines/reference/noUnusedLocals_selfReference.types b/tests/baselines/reference/noUnusedLocals_selfReference.types index 7e75062db34d5..cbaa413c65152 100644 --- a/tests/baselines/reference/noUnusedLocals_selfReference.types +++ b/tests/baselines/reference/noUnusedLocals_selfReference.types @@ -30,17 +30,6 @@ enum E { A = 0, B = E.A } >E : typeof E >A : E -// Does not detect mutual recursion. -function g() { D; } ->g : () => void ->D : typeof D - -class D { m() { g; } } ->D : D ->m : () => void ->g : () => void - -// Does not work on private methods. class P { private m() { this.m; } } >P : P >m : () => void @@ -51,3 +40,13 @@ class P { private m() { this.m; } } P; >P : typeof P +// Does not detect mutual recursion. +function g() { D; } +>g : () => void +>D : typeof D + +class D { m() { g; } } +>D : D +>m : () => void +>g : () => void + diff --git a/tests/cases/compiler/noUnusedLocals_selfReference.ts b/tests/cases/compiler/noUnusedLocals_selfReference.ts index fc6b02b600634..10ec9ebf782a9 100644 --- a/tests/cases/compiler/noUnusedLocals_selfReference.ts +++ b/tests/cases/compiler/noUnusedLocals_selfReference.ts @@ -13,10 +13,9 @@ class C { } enum E { A = 0, B = E.A } +class P { private m() { this.m; } } +P; + // Does not detect mutual recursion. function g() { D; } class D { m() { g; } } - -// Does not work on private methods. -class P { private m() { this.m; } } -P; From 49cfbb438f43cc93d49e603fac2da08664623ef0 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Oct 2017 12:18:17 -0700 Subject: [PATCH 197/246] Added test for windows style paths watched directories --- .../unittests/tsserverProjectSystem.ts | 40 +++++++++++++++++++ src/harness/virtualFileSystemWithWatch.ts | 31 +++++++++++--- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 175b579103f57..bc88a4b3837d9 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -5760,4 +5760,44 @@ namespace ts.projectSystem { } }); }); + + describe("Watched recursive directories with windows style file system", () => { + function verifyWatchedDirectories(useProjectAtRoot: boolean) { + const root = useProjectAtRoot ? "c:/" : "c:/myfolder/allproject/"; + const configFile: FileOrFolder = { + path: root + "project/tsconfig.json", + content: "{}" + }; + const file1: FileOrFolder = { + path: root + "project/file1.ts", + content: "let x = 10;" + }; + const file2: FileOrFolder = { + path: root + "project/file2.ts", + content: "let y = 10;" + }; + const files = [configFile, file1, file2, libFile]; + const host = createServerHost(files, { useWindowsStylePaths: true }); + const projectService = createProjectService(host); + projectService.openClientFile(file1.path); + const project = projectService.configuredProjects.get(configFile.path); + assert.isDefined(project); + const winsowsStyleLibFilePath = "c:/" + libFile.path.substring(1); + checkProjectActualFiles(project, files.map(f => f === libFile ? winsowsStyleLibFilePath : f.path)); + checkWatchedFiles(host, mapDefined(files, f => f === libFile ? winsowsStyleLibFilePath : f === file1 ? undefined : f.path)); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, [ + root + "project", + root + "project/node_modules/@types" + ].concat(useProjectAtRoot ? [] : [root + nodeModulesAtTypes]), /*recursive*/ true); + } + + it("When project is in rootFolder", () => { + verifyWatchedDirectories(/*useProjectAtRoot*/ true); + }); + + it("When files at some folder other than root", () => { + verifyWatchedDirectories(/*useProjectAtRoot*/ false); + }); + }); } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 67b3e264db4ad..4463bbac7a556 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -28,6 +28,7 @@ namespace ts.TestFSWithWatch { executingFilePath?: string; currentDirectory?: string; newLine?: string; + useWindowsStylePaths?: boolean; } export function createWatchedSystem(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { @@ -39,7 +40,8 @@ namespace ts.TestFSWithWatch { params.executingFilePath || getExecutingFilePathFromLibFile(), params.currentDirectory || "/", fileOrFolderList, - params.newLine); + params.newLine, + params.useWindowsStylePaths); return host; } @@ -52,7 +54,8 @@ namespace ts.TestFSWithWatch { params.executingFilePath || getExecutingFilePathFromLibFile(), params.currentDirectory || "/", fileOrFolderList, - params.newLine); + params.newLine, + params.useWindowsStylePaths); return host; } @@ -230,11 +233,14 @@ namespace ts.TestFSWithWatch { readonly watchedDirectories = createMultiMap(); readonly watchedDirectoriesRecursive = createMultiMap(); readonly watchedFiles = createMultiMap(); + private readonly executingFilePath: string; + private readonly currentDirectory: string; - constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: ReadonlyArray, public readonly newLine = "\n") { + constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean) { this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName); - + this.executingFilePath = this.getHostSpecificPath(executingFilePath); + this.currentDirectory = this.getHostSpecificPath(currentDirectory); this.reloadFS(fileOrFolderList); } @@ -250,11 +256,24 @@ namespace ts.TestFSWithWatch { return this.toPath(this.toNormalizedAbsolutePath(s)); } + getHostSpecificPath(s: string) { + if (this.useWindowsStylePath && s.startsWith(directorySeparator)) { + return "c:/" + s.substring(1); + } + return s; + } + reloadFS(fileOrFolderList: ReadonlyArray) { const mapNewLeaves = createMap(); const isNewFs = this.fs.size === 0; - // always inject safelist file in the list of files - for (const fileOrDirectory of fileOrFolderList.concat(this.withSafeList ? safeList : [])) { + fileOrFolderList = fileOrFolderList.concat(this.withSafeList ? safeList : []); + const filesOrFoldersToLoad: ReadonlyArray = !this.useWindowsStylePath ? fileOrFolderList : + fileOrFolderList.map(f => { + const result = clone(f); + result.path = this.getHostSpecificPath(f.path); + return result; + }); + for (const fileOrDirectory of filesOrFoldersToLoad) { const path = this.toFullPath(fileOrDirectory.path); mapNewLeaves.set(path, true); // If its a change From a5861af00e06ee8201f90446cb0ae37173ddde0b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Oct 2017 14:13:12 -0700 Subject: [PATCH 198/246] Handle when directory watcher is invoked on file change Fixes #19206 --- src/compiler/core.ts | 17 ++++++++-- src/compiler/watch.ts | 13 ++++++-- src/harness/unittests/tscWatchMode.ts | 40 +++++++++++++++++++++++ src/harness/virtualFileSystemWithWatch.ts | 9 +++-- 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 542435b84f901..8f3eacae667bb 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2701,8 +2701,14 @@ namespace ts { export function assertTypeIsNever(_: never): void { } + export interface FileAndDirectoryExistence { + fileExists: boolean; + directoryExists: boolean; + } + export interface CachedDirectoryStructureHost extends DirectoryStructureHost { - addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): void; + /** Returns the queried result for the file exists and directory exists if at all it was done */ + addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): FileAndDirectoryExistence | undefined; addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void; clearCache(): void; } @@ -2872,8 +2878,13 @@ namespace ts { if (parentResult) { const baseName = getBaseNameOfFileName(fileOrDirectory); if (parentResult) { - updateFilesOfFileSystemEntry(parentResult, baseName, host.fileExists(fileOrDirectoryPath)); - updateFileSystemEntry(parentResult.directories, baseName, host.directoryExists(fileOrDirectoryPath)); + const fsQueryResult: FileAndDirectoryExistence = { + fileExists: host.fileExists(fileOrDirectoryPath), + directoryExists: host.directoryExists(fileOrDirectoryPath) + }; + updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists); + updateFileSystemEntry(parentResult.directories, baseName, fsQueryResult.directoryExists); + return fsQueryResult; } } } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 4fc67c1cc8fc2..6f61469197b21 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -605,8 +605,17 @@ namespace ts { const fileOrDirectoryPath = toPath(fileOrDirectory); // Since the file existance changed, update the sourceFiles cache - (directoryStructureHost as CachedDirectoryStructureHost).addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); - removeSourceFile(fileOrDirectoryPath); + const result = (directoryStructureHost as CachedDirectoryStructureHost).addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); + + // Instead of deleting the file, mark it as changed instead + // Many times node calls add/remove/file when watching directories recursively + const hostSourceFile = sourceFilesCache.get(fileOrDirectoryPath); + if (hostSourceFile && !isString(hostSourceFile) && (result ? result.fileExists : directoryStructureHost.fileExists(fileOrDirectory))) { + hostSourceFile.version++; + } + else { + removeSourceFile(fileOrDirectoryPath); + } // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index b25a7b1eb53c2..3c2856f3caffc 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1819,4 +1819,44 @@ declare module "fs" { checkOutputErrors(host); }); }); + + describe("tsc-watch with when module emit is specified as node", () => { + it("when instead of filechanged recursive directory watcher is invoked", () => { + const configFile: FileOrFolder = { + path: "/a/rootFolder/project/tsconfig.json", + content: JSON.stringify({ + "compilerOptions": { + "module": "none", + "allowJs": true, + "outDir": "Static/scripts/" + }, + "include": [ + "Scripts/**/*" + ], + }) + }; + const outputFolder = "/a/rootFolder/project/Static/scripts/"; + const file1: FileOrFolder = { + path: "/a/rootFolder/project/Scripts/TypeScript.ts", + content: "var z = 10;" + }; + const file2: FileOrFolder = { + path: "/a/rootFolder/project/Scripts/Javascript.js", + content: "var zz = 10;" + }; + const files = [configFile, file1, file2, libFile]; + const host = createWatchedSystem(files); + const watch = createWatchModeWithConfigFile(configFile.path, host); + + checkProgramActualFiles(watch(), mapDefined(files, f => f === configFile ? undefined : f.path)); + file1.content = "var zz30 = 100;"; + host.reloadFS(files, /*invokeDirectoryWatcherInsteadOfFileChanged*/ true); + host.runQueuedTimeoutCallbacks(); + + checkProgramActualFiles(watch(), mapDefined(files, f => f === configFile ? undefined : f.path)); + const outputFile1 = changeExtension((outputFolder + getBaseFileName(file1.path)), ".js"); + assert.isTrue(host.fileExists(outputFile1)); + assert.equal(host.readFile(outputFile1), file1.content + host.newLine); + }); + }); } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 67b3e264db4ad..c74be545f8fc4 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -250,7 +250,7 @@ namespace ts.TestFSWithWatch { return this.toPath(this.toNormalizedAbsolutePath(s)); } - reloadFS(fileOrFolderList: ReadonlyArray) { + reloadFS(fileOrFolderList: ReadonlyArray, invokeDirectoryWatcherInsteadOfFileChanged?: boolean) { const mapNewLeaves = createMap(); const isNewFs = this.fs.size === 0; // always inject safelist file in the list of files @@ -265,7 +265,12 @@ namespace ts.TestFSWithWatch { // Update file if (currentEntry.content !== fileOrDirectory.content) { currentEntry.content = fileOrDirectory.content; - this.invokeFileWatcher(currentEntry.fullPath, FileWatcherEventKind.Changed); + if (invokeDirectoryWatcherInsteadOfFileChanged) { + this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath); + } + else { + this.invokeFileWatcher(currentEntry.fullPath, FileWatcherEventKind.Changed); + } } } else { From d05443bb1d3c346fbef4c2468ff06b00041b688d Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 17 Oct 2017 15:04:09 -0700 Subject: [PATCH 199/246] Add quickfix and refactoring to install @types packages (#19130) * Add quickfix and refactoring to install @types packages * Move `validatePackageName` to `jsTyping.ts` * Remove combinePaths overloads * Respond to code review * Update api baselines * Use native PromiseConstructor * Return false instead of undefined * Remove getProjectRootPath * Update api --- scripts/buildProtocol.ts | 33 ++++--- src/compiler/core.ts | 2 +- src/compiler/moduleNameResolver.ts | 32 ++++--- src/harness/fourslash.ts | 55 +++++++++-- src/harness/harnessLanguageService.ts | 7 ++ src/harness/unittests/compileOnSave.ts | 2 +- src/harness/unittests/extractTestHelpers.ts | 10 ++ src/harness/unittests/projectErrors.ts | 10 +- src/harness/unittests/session.ts | 10 +- .../unittests/tsserverProjectSystem.ts | 41 +++++---- src/harness/unittests/typingsInstaller.ts | 20 ++-- src/server/client.ts | 4 +- src/server/project.ts | 10 ++ src/server/protocol.ts | 24 ++++- src/server/server.ts | 54 ++++++++++- src/server/session.ts | 75 ++++++++++----- src/server/shared.ts | 2 + src/server/types.ts | 40 +++++++- src/server/typingsCache.ts | 17 ++++ .../typingsInstaller/nodeTypingsInstaller.ts | 50 ++++++++-- .../typingsInstaller/typingsInstaller.ts | 74 ++------------- src/services/codefixes/fixCannotFindModule.ts | 35 +++++++ src/services/codefixes/fixes.ts | 1 + src/services/jsTyping.ts | 61 +++++++++++++ src/services/refactorProvider.ts | 1 + .../refactors/installTypesForPackage.ts | 63 +++++++++++++ src/services/refactors/refactors.ts | 1 + src/services/services.ts | 17 +++- src/services/types.ts | 32 ++++++- src/services/utilities.ts | 9 ++ .../reference/api/tsserverlibrary.d.ts | 91 +++++++++++++++---- tests/baselines/reference/api/typescript.d.ts | 23 ++++- .../fourslash/codeFixCannotFindModule.ts | 15 +++ tests/cases/fourslash/fourslash.ts | 11 ++- .../refactorInstallTypesForPackage.ts | 25 +++++ ...ctorInstallTypesForPackage_importEquals.ts | 25 +++++ 36 files changed, 773 insertions(+), 209 deletions(-) create mode 100644 src/services/codefixes/fixCannotFindModule.ts create mode 100644 src/services/refactors/installTypesForPackage.ts create mode 100644 tests/cases/fourslash/codeFixCannotFindModule.ts create mode 100644 tests/cases/fourslash/refactorInstallTypesForPackage.ts create mode 100644 tests/cases/fourslash/refactorInstallTypesForPackage_importEquals.ts diff --git a/scripts/buildProtocol.ts b/scripts/buildProtocol.ts index c2ac33c83fc19..899ab700bf372 100644 --- a/scripts/buildProtocol.ts +++ b/scripts/buildProtocol.ts @@ -51,22 +51,25 @@ class DeclarationsWalker { return this.processType((type).typeArguments[0]); } else { - for (const decl of s.getDeclarations()) { - const sourceFile = decl.getSourceFile(); - if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") { - return; - } - if (decl.kind === ts.SyntaxKind.EnumDeclaration && !isStringEnum(decl as ts.EnumDeclaration)) { - this.removedTypes.push(type); - return; - } - else { - // splice declaration in final d.ts file - let text = decl.getFullText(); - this.text += `${text}\n`; - // recursively pull all dependencies into result dts file + const declarations = s.getDeclarations(); + if (declarations) { + for (const decl of declarations) { + const sourceFile = decl.getSourceFile(); + if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") { + return; + } + if (decl.kind === ts.SyntaxKind.EnumDeclaration && !isStringEnum(decl as ts.EnumDeclaration)) { + this.removedTypes.push(type); + return; + } + else { + // splice declaration in final d.ts file + let text = decl.getFullText(); + this.text += `${text}\n`; + // recursively pull all dependencies into result dts file - this.visitTypeNodes(decl); + this.visitTypeNodes(decl); + } } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 542435b84f901..bc28965b7c5da 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1861,7 +1861,7 @@ namespace ts { return i < 0 ? path : path.substring(i + 1); } - export function combinePaths(path1: string, path2: string) { + export function combinePaths(path1: string, path2: string): string { if (!(path1 && path1.length)) return path2; if (!(path2 && path2.length)) return path1; if (getRootLength(path2) !== 0) return path2; diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index a0e045cf0f259..b0633ef4d5a26 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1005,7 +1005,8 @@ namespace ts { return withPackageId(packageId, pathAndExtension); } - function getPackageName(moduleName: string): { packageName: string, rest: string } { + /* @internal */ + export function getPackageName(moduleName: string): { packageName: string, rest: string } { let idx = moduleName.indexOf(directorySeparator); if (moduleName[0] === "@") { idx = moduleName.indexOf(directorySeparator, idx + 1); @@ -1063,18 +1064,27 @@ namespace ts { const mangledScopedPackageSeparator = "__"; /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ - function mangleScopedPackage(moduleName: string, state: ModuleResolutionState): string { - if (startsWith(moduleName, "@")) { - const replaceSlash = moduleName.replace(ts.directorySeparator, mangledScopedPackageSeparator); - if (replaceSlash !== moduleName) { - const mangled = replaceSlash.slice(1); // Take off the "@" - if (state.traceEnabled) { - trace(state.host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); - } - return mangled; + function mangleScopedPackage(packageName: string, state: ModuleResolutionState): string { + const mangled = getMangledNameForScopedPackage(packageName); + if (state.traceEnabled && mangled !== packageName) { + trace(state.host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); + } + return mangled; + } + + /* @internal */ + export function getTypesPackageName(packageName: string): string { + return `@types/${getMangledNameForScopedPackage(packageName)}`; + } + + function getMangledNameForScopedPackage(packageName: string): string { + if (startsWith(packageName, "@")) { + const replaceSlash = packageName.replace(ts.directorySeparator, mangledScopedPackageSeparator); + if (replaceSlash !== packageName) { + return replaceSlash.slice(1); // Take off the "@" } } - return moduleName; + return packageName; } /* @internal */ diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 493b0187b57ad..9ac2aac764529 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -953,6 +953,10 @@ namespace FourSlash { return this.getChecker().getSymbolsInScope(node, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace); } + public setTypesRegistry(map: ts.MapLike): void { + this.languageServiceAdapterHost.typesRegistry = ts.createMapFromTemplate(map); + } + public verifyTypeOfSymbolAtLocation(range: Range, symbol: ts.Symbol, expected: string): void { const node = this.goToAndGetNode(range); const checker = this.getChecker(); @@ -2777,16 +2781,26 @@ Actual: ${stringify(fullActual)}`); } } - public verifyCodeFixAvailable(negative: boolean) { - const codeFix = this.getCodeFixActions(this.activeFile.fileName); + public verifyCodeFixAvailable(negative: boolean, info: FourSlashInterface.VerifyCodeFixAvailableOptions[] | undefined) { + const codeFixes = this.getCodeFixActions(this.activeFile.fileName); - if (negative && codeFix.length) { - this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found one.`); + if (negative) { + if (codeFixes.length) { + this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found one.`); + } + return; } - if (!(negative || codeFix.length)) { + if (!codeFixes.length) { this.raiseError(`verifyCodeFixAvailable failed - expected code fixes but none found.`); } + if (info) { + assert.equal(info.length, codeFixes.length); + ts.zipWith(codeFixes, info, (fix, info) => { + assert.equal(fix.description, info.description); + this.assertObjectsEqual(fix.commands, info.commands); + }); + } } public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string) { @@ -2830,6 +2844,14 @@ Actual: ${stringify(fullActual)}`); } } + public verifyRefactor({ name, actionName, refactors }: FourSlashInterface.VerifyRefactorOptions) { + const selection = this.getSelection(); + + const actualRefactors = (this.languageService.getApplicableRefactors(this.activeFile.fileName, selection) || ts.emptyArray) + .filter(r => r.name === name && r.actions.some(a => a.name === actionName)); + this.assertObjectsEqual(actualRefactors, refactors); + } + public verifyApplicableRefactorAvailableForRange(negative: boolean) { const ranges = this.getRanges(); if (!(ranges && ranges.length === 1)) { @@ -3614,6 +3636,10 @@ namespace FourSlashInterface { public symbolsInScope(range: FourSlash.Range): ts.Symbol[] { return this.state.symbolsInScope(range); } + + public setTypesRegistry(map: ts.MapLike): void { + this.state.setTypesRegistry(map); + } } export class GoTo { @@ -3789,8 +3815,8 @@ namespace FourSlashInterface { this.state.verifyCodeFix(options); } - public codeFixAvailable() { - this.state.verifyCodeFixAvailable(this.negative); + public codeFixAvailable(options?: VerifyCodeFixAvailableOptions[]) { + this.state.verifyCodeFixAvailable(this.negative, options); } public applicableRefactorAvailableAtMarker(markerName: string) { @@ -3801,6 +3827,10 @@ namespace FourSlashInterface { this.state.verifyApplicableRefactorAvailableForRange(this.negative); } + public refactor(options: VerifyRefactorOptions) { + this.state.verifyRefactor(options); + } + public refactorAvailable(name: string, actionName?: string) { this.state.verifyRefactorAvailable(this.negative, name, actionName); } @@ -4449,6 +4479,17 @@ namespace FourSlashInterface { index?: number; } + export interface VerifyCodeFixAvailableOptions { + description: string; + commands?: ts.CodeActionCommand[]; + } + + export interface VerifyRefactorOptions { + name: string; + actionName: string; + refactors: ts.ApplicableRefactorInfo[]; + } + export interface VerifyCompletionActionOptions extends NewContentOptions { name: string; description: string; diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 527824ee145aa..a12554addfe6f 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -123,6 +123,7 @@ namespace Harness.LanguageService { } export class LanguageServiceAdapterHost { + public typesRegistry: ts.Map | undefined; protected virtualFileSystem: Utils.VirtualFileSystem = new Utils.VirtualFileSystem(virtualFileSystemRoot, /*useCaseSensitiveFilenames*/false); constructor(protected cancellationToken = DefaultHostCancellationToken.Instance, @@ -182,6 +183,11 @@ namespace Harness.LanguageService { /// Native adapter class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost { + isKnownTypesPackageName(name: string): boolean { + return this.typesRegistry && this.typesRegistry.has(name); + } + installPackage = ts.notImplemented; + getCompilationSettings() { return this.settings; } getCancellationToken() { return this.cancellationToken; } getDirectories(path: string): string[] { @@ -493,6 +499,7 @@ namespace Harness.LanguageService { getCodeFixesAtPosition(): ts.CodeAction[] { throw new Error("Not supported on the shim."); } + applyCodeActionCommand = ts.notImplemented; getCodeFixDiagnostics(): ts.Diagnostic[] { throw new Error("Not supported on the shim."); } diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index fdec5b192ee83..7be6ab5b323ec 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -12,7 +12,7 @@ namespace ts.projectSystem { describe("CompileOnSave affected list", () => { function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { - const response: server.protocol.CompileOnSaveAffectedFileListSingleProject[] = session.executeCommand(request).response; + const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; const actualResult = response.sort((list1, list2) => compareStrings(list1.projectFileName, list2.projectFileName)); expectedFileList = expectedFileList.sort((list1, list2) => compareStrings(list1.projectFileName, list2.projectFileName)); diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index 1b51cdadc2785..49c2c1d327704 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -97,6 +97,14 @@ namespace ts { return rulesProvider; } + const notImplementedHost: LanguageServiceHost = { + getCompilationSettings: notImplemented, + getScriptFileNames: notImplemented, + getScriptVersion: notImplemented, + getScriptSnapshot: notImplemented, + getDefaultLibFileName: notImplemented, + }; + export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage) { const t = extractTest(text); const selectionRange = t.ranges.get("selection"); @@ -125,6 +133,7 @@ namespace ts { file: sourceFile, startPosition: selectionRange.start, endPosition: selectionRange.end, + host: notImplementedHost, rulesProvider: getRuleProvider() }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end)); @@ -188,6 +197,7 @@ namespace ts { file: sourceFile, startPosition: selectionRange.start, endPosition: selectionRange.end, + host: notImplementedHost, rulesProvider: getRuleProvider() }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end)); diff --git a/src/harness/unittests/projectErrors.ts b/src/harness/unittests/projectErrors.ts index d72168383c170..dae465a3ef333 100644 --- a/src/harness/unittests/projectErrors.ts +++ b/src/harness/unittests/projectErrors.ts @@ -57,7 +57,7 @@ namespace ts.projectSystem { }); checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response; + const diags = session.executeCommand(compilerOptionsRequest).response as server.protocol.DiagnosticWithLinePosition[]; // only file1 exists - expect error checkDiagnosticsWithLinePos(diags, ["File '/a/b/applib.ts' not found."]); } @@ -65,7 +65,7 @@ namespace ts.projectSystem { { // only file2 exists - expect error checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response; + const diags = session.executeCommand(compilerOptionsRequest).response as server.protocol.DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, ["File '/a/b/app.ts' not found."]); } @@ -73,7 +73,7 @@ namespace ts.projectSystem { { // both files exist - expect no errors checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response; + const diags = session.executeCommand(compilerOptionsRequest).response as server.protocol.DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, []); } }); @@ -103,13 +103,13 @@ namespace ts.projectSystem { seq: 2, arguments: { projectFileName: project.getProjectName() } }; - let diags = session.executeCommand(compilerOptionsRequest).response; + let diags = session.executeCommand(compilerOptionsRequest).response as server.protocol.DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, ["File '/a/b/applib.ts' not found."]); host.reloadFS([file1, file2, config, libFile]); checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diags = session.executeCommand(compilerOptionsRequest).response; + diags = session.executeCommand(compilerOptionsRequest).response as server.protocol.DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, []); }); diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 3b5efc2d6defb..fbef9cb455841 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -315,7 +315,7 @@ namespace ts.server { item: false }; const command = "newhandle"; - const result = { + const result: ts.server.HandlerResponse = { response: respBody, responseRequired: true }; @@ -332,7 +332,7 @@ namespace ts.server { const respBody = { item: false }; - const resp = { + const resp: ts.server.HandlerResponse = { response: respBody, responseRequired: true }; @@ -372,7 +372,7 @@ namespace ts.server { }; const command = "test"; - session.output(body, command); + session.output(body, command, /*reqSeq*/ 0); expect(lastSent).to.deep.equal({ seq: 0, @@ -475,7 +475,7 @@ namespace ts.server { }; const command = "test"; - session.output(body, command); + session.output(body, command, /*reqSeq*/ 0); expect(session.lastSent).to.deep.equal({ seq: 0, @@ -542,7 +542,7 @@ namespace ts.server { handleRequest(msg: protocol.Request) { let response: protocol.Response; try { - ({ response } = this.executeCommand(msg)); + response = this.executeCommand(msg).response as protocol.Response; } catch (e) { this.output(undefined, msg.command, msg.seq, e.toString()); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index bc88a4b3837d9..943fae87af086 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -70,6 +70,9 @@ namespace ts.projectSystem { protected postExecActions: PostExecAction[] = []; + isKnownTypesPackageName = notImplemented; + installPackage = notImplemented; + executePendingCommands() { const actionsToRun = this.postExecActions; this.postExecActions = []; @@ -769,7 +772,7 @@ namespace ts.projectSystem { ); // Two errors: CommonFile2 not found and cannot find name y - let diags: server.protocol.Diagnostic[] = session.executeCommand(getErrRequest).response; + let diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyDiagnostics(diags, [ { diagnosticMessage: Diagnostics.Cannot_find_name_0, errorTextArguments: ["y"] }, { diagnosticMessage: Diagnostics.File_0_not_found, errorTextArguments: [commonFile2.path] } @@ -781,7 +784,7 @@ namespace ts.projectSystem { assert.strictEqual(projectService.inferredProjects[0], project, "Inferred project should be same"); checkProjectRootFiles(project, [file1.path]); checkProjectActualFiles(project, [file1.path, libFile.path, commonFile2.path]); - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); }); @@ -2614,11 +2617,11 @@ namespace ts.projectSystem { // Try to find some interface type defined in lib.d.ts const libTypeNavToRequest = makeSessionRequest(CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path }); - const items: protocol.NavtoItem[] = session.executeCommand(libTypeNavToRequest).response; + const items = session.executeCommand(libTypeNavToRequest).response as protocol.NavtoItem[]; assert.isFalse(containsNavToItem(items, "Document", "interface"), `Found lib.d.ts symbol in JavaScript project nav to request result.`); const localFunctionNavToRequst = makeSessionRequest(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); - const items2: protocol.NavtoItem[] = session.executeCommand(localFunctionNavToRequst).response; + const items2 = session.executeCommand(localFunctionNavToRequst).response as protocol.NavtoItem[]; assert.isTrue(containsNavToItem(items2, "foo", "function"), `Cannot find function symbol "foo".`); }); }); @@ -3073,7 +3076,7 @@ namespace ts.projectSystem { server.CommandNames.SemanticDiagnosticsSync, { file: file1.path } ); - let diags: server.protocol.Diagnostic[] = session.executeCommand(getErrRequest).response; + let diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); const moduleFileOldPath = moduleFile.path; @@ -3081,7 +3084,7 @@ namespace ts.projectSystem { moduleFile.path = moduleFileNewPath; host.reloadFS([moduleFile, file1]); host.runQueuedTimeoutCallbacks(); - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyDiagnostics(diags, [ { diagnosticMessage: Diagnostics.Cannot_find_module_0, errorTextArguments: ["./moduleFile"] } ]); @@ -3099,7 +3102,7 @@ namespace ts.projectSystem { session.executeCommand(changeRequest); host.runQueuedTimeoutCallbacks(); - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); }); @@ -3124,7 +3127,7 @@ namespace ts.projectSystem { server.CommandNames.SemanticDiagnosticsSync, { file: file1.path } ); - let diags: server.protocol.Diagnostic[] = session.executeCommand(getErrRequest).response; + let diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); const moduleFileOldPath = moduleFile.path; @@ -3132,7 +3135,7 @@ namespace ts.projectSystem { moduleFile.path = moduleFileNewPath; host.reloadFS([moduleFile, file1, configFile]); host.runQueuedTimeoutCallbacks(); - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyDiagnostics(diags, [ { diagnosticMessage: Diagnostics.Cannot_find_module_0, errorTextArguments: ["./moduleFile"] } ]); @@ -3140,7 +3143,7 @@ namespace ts.projectSystem { moduleFile.path = moduleFileOldPath; host.reloadFS([moduleFile, file1, configFile]); host.runQueuedTimeoutCallbacks(); - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); }); @@ -3207,7 +3210,7 @@ namespace ts.projectSystem { server.CommandNames.SemanticDiagnosticsSync, { file: file1.path } ); - let diags: server.protocol.Diagnostic[] = session.executeCommand(getErrRequest).response; + let diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyDiagnostics(diags, [ { diagnosticMessage: Diagnostics.Cannot_find_module_0, errorTextArguments: ["./moduleFile"] } ]); @@ -3223,7 +3226,7 @@ namespace ts.projectSystem { session.executeCommand(changeRequest); // Recheck - diags = session.executeCommand(getErrRequest).response; + diags = session.executeCommand(getErrRequest).response as server.protocol.Diagnostic[]; verifyNoDiagnostics(diags); }); }); @@ -3923,7 +3926,7 @@ namespace ts.projectSystem { command: server.CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName: projectName } - }).response; + }).response as ReadonlyArray; assert.isTrue(diags.length === 0); session.executeCommand({ @@ -3937,7 +3940,7 @@ namespace ts.projectSystem { command: server.CommandNames.CompilerOptionsDiagnosticsFull, seq: 4, arguments: { projectFileName: projectName } - }).response; + }).response as ReadonlyArray; assert.isTrue(diagsAfterUpdate.length === 0); }); @@ -3964,7 +3967,7 @@ namespace ts.projectSystem { command: server.CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName } - }).response; + }).response as ReadonlyArray; assert.isTrue(diags.length === 0); session.executeCommand({ @@ -3982,7 +3985,7 @@ namespace ts.projectSystem { command: server.CommandNames.CompilerOptionsDiagnosticsFull, seq: 4, arguments: { projectFileName } - }).response; + }).response as ReadonlyArray; assert.isTrue(diagsAfterUpdate.length === 0); }); }); @@ -4463,7 +4466,7 @@ namespace ts.projectSystem { command: server.CommandNames.SemanticDiagnosticsSync, seq: 2, arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true } - }).response; + }).response as ReadonlyArray; assert.isTrue(diags.length === 2); configFile.content = configFileContentWithoutCommentLine; @@ -4474,7 +4477,7 @@ namespace ts.projectSystem { command: server.CommandNames.SemanticDiagnosticsSync, seq: 2, arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true } - }).response; + }).response as ReadonlyArray; assert.isTrue(diagsAfterEdit.length === 2); verifyDiagnostic(diags[0], diagsAfterEdit[0]); @@ -4864,7 +4867,7 @@ namespace ts.projectSystem { line: undefined, offset: undefined }); - const { response } = session.executeCommand(getDefinitionRequest); + const response = session.executeCommand(getDefinitionRequest).response as server.protocol.FileSpan[]; assert.equal(response[0].file, moduleFile.path, "Should go to definition of vessel: response: " + JSON.stringify(response)); callsTrackingHost.verifyNoHostCalls(); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index e644f8730107b..fb1a7a26a7ae0 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -4,6 +4,8 @@ namespace ts.projectSystem { import TI = server.typingsInstaller; + import validatePackageName = JsTyping.validatePackageName; + import PackageNameValidationResult = JsTyping.PackageNameValidationResult; interface InstallerParams { globalTypingsCacheLocation?: string; @@ -266,7 +268,7 @@ namespace ts.projectSystem { }; const host = createServerHost([file1]); let enqueueIsCalled = false; - const installer = new (class extends Installer { + const installer: Installer = new (class extends Installer { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery") }); } @@ -983,21 +985,21 @@ namespace ts.projectSystem { for (let i = 0; i < 8; i++) { packageName += packageName; } - assert.equal(TI.validatePackageName(packageName), TI.PackageNameValidationResult.NameTooLong); + assert.equal(validatePackageName(packageName), PackageNameValidationResult.NameTooLong); }); it("name cannot start with dot", () => { - assert.equal(TI.validatePackageName(".foo"), TI.PackageNameValidationResult.NameStartsWithDot); + assert.equal(validatePackageName(".foo"), PackageNameValidationResult.NameStartsWithDot); }); it("name cannot start with underscore", () => { - assert.equal(TI.validatePackageName("_foo"), TI.PackageNameValidationResult.NameStartsWithUnderscore); + assert.equal(validatePackageName("_foo"), PackageNameValidationResult.NameStartsWithUnderscore); }); it("scoped packages not supported", () => { - assert.equal(TI.validatePackageName("@scope/bar"), TI.PackageNameValidationResult.ScopedPackagesNotSupported); + assert.equal(validatePackageName("@scope/bar"), PackageNameValidationResult.ScopedPackagesNotSupported); }); it("non URI safe characters are not supported", () => { - assert.equal(TI.validatePackageName(" scope "), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); - assert.equal(TI.validatePackageName("; say ‘Hello from TypeScript!’ #"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); - assert.equal(TI.validatePackageName("a/b/c"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); + assert.equal(validatePackageName(" scope "), PackageNameValidationResult.NameContainsNonURISafeCharacters); + assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), PackageNameValidationResult.NameContainsNonURISafeCharacters); + assert.equal(validatePackageName("a/b/c"), PackageNameValidationResult.NameContainsNonURISafeCharacters); }); }); @@ -1250,7 +1252,7 @@ namespace ts.projectSystem { const host = createServerHost([f1, packageFile]); let beginEvent: server.BeginInstallTypes; let endEvent: server.EndInstallTypes; - const installer = new (class extends Installer { + const installer: Installer = new (class extends Installer { constructor() { super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("commander") }); } diff --git a/src/server/client.ts b/src/server/client.ts index 39e30848e3e52..2781d7cf20ae5 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -14,7 +14,7 @@ namespace ts.server { } /* @internal */ - export function extractMessage(message: string) { + export function extractMessage(message: string): string { // Read the content length const contentLengthPrefix = "Content-Length: "; const lines = message.split(/\r?\n/); @@ -542,6 +542,8 @@ namespace ts.server { return response.body.map(entry => this.convertCodeActions(entry, file)); } + applyCodeActionCommand = notImplemented; + private createFileLocationOrRangeRequestArgs(positionOrRange: number | TextRange, fileName: string): protocol.FileLocationOrRangeRequestArgs { return typeof positionOrRange === "number" ? this.createFileLocationRequestArgs(fileName, positionOrRange) diff --git a/src/server/project.ts b/src/server/project.ts index 9c3fab63d2306..725ce725c3881 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -242,6 +242,16 @@ namespace ts.server { this.markAsDirty(); } + isKnownTypesPackageName(name: string): boolean { + return this.typingsCache.isKnownTypesPackageName(name); + } + installPackage(options: InstallPackageOptions): PromiseLike { + return this.typingsCache.installPackage({ ...options, projectRootPath: this.toPath(this.currentDirectory) }); + } + private get typingsCache(): TypingsCache { + return this.projectService.typingsCache; + } + // Method of LanguageServiceHost getCompilationSettings() { return this.compilerOptions; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 7b9e9fe80969a..35e9f20d05825 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -94,6 +94,7 @@ namespace ts.server.protocol { BreakpointStatement = "breakpointStatement", CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects", GetCodeFixes = "getCodeFixes", + ApplyCodeActionCommand = "applyCodeActionCommand", /* @internal */ GetCodeFixesFull = "getCodeFixes-full", GetSupportedCodeFixes = "getSupportedCodeFixes", @@ -125,6 +126,8 @@ namespace ts.server.protocol { * Client-initiated request message */ export interface Request extends Message { + type: "request"; + /** * The command to execute */ @@ -147,6 +150,8 @@ namespace ts.server.protocol { * Server-initiated event message */ export interface Event extends Message { + type: "event"; + /** * Name of event */ @@ -162,6 +167,8 @@ namespace ts.server.protocol { * Response by server to client request message. */ export interface Response extends Message { + type: "response"; + /** * Sequence number of the request message. */ @@ -178,7 +185,8 @@ namespace ts.server.protocol { command: string; /** - * Contains error message if success === false. + * If success === false, this should always be provided. + * Otherwise, may (or may not) contain a success message. */ message?: string; @@ -520,6 +528,14 @@ namespace ts.server.protocol { arguments: CodeFixRequestArgs; } + export interface ApplyCodeActionCommandRequest extends Request { + command: CommandTypes.ApplyCodeActionCommand; + arguments: ApplyCodeActionCommandRequestArgs; + } + + // All we need is the `success` and `message` fields of Response. + export interface ApplyCodeActionCommandResponse extends Response {} + export interface FileRangeRequestArgs extends FileRequestArgs { /** * The line number for the request (1-based). @@ -564,6 +580,10 @@ namespace ts.server.protocol { errorCodes?: number[]; } + export interface ApplyCodeActionCommandRequestArgs extends FileRequestArgs { + command: {}; + } + /** * Response for GetCodeFixes request. */ @@ -1541,6 +1561,8 @@ namespace ts.server.protocol { description: string; /** Text changes to apply to each file as part of the code action */ changes: FileCodeEdits[]; + /** A command is an opaque object that should be passed to `ApplyCodeActionCommandRequestArgs` without modification. */ + commands?: {}[]; } /** diff --git a/src/server/server.ts b/src/server/server.ts index 17905ece33ade..decf614cf8ea7 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -250,6 +250,9 @@ namespace ts.server { private activeRequestCount = 0; private requestQueue: QueuedOperation[] = []; private requestMap = createMap(); // Maps operation ID to newest requestQueue entry with that ID + /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ + private requestedRegistry: boolean; + private typesRegistryCache: Map | undefined; // This number is essentially arbitrary. Processing more than one typings request // at a time makes sense, but having too many in the pipe results in a hang @@ -258,7 +261,7 @@ namespace ts.server { // buffer, but we have yet to find a way to retrieve that value. private static readonly maxActiveRequestCount = 10; private static readonly requestDelayMillis = 100; - + private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: any): void }; constructor( private readonly telemetryEnabled: boolean, @@ -278,6 +281,31 @@ namespace ts.server { } } + isKnownTypesPackageName(name: string): boolean { + // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package. + const validationResult = JsTyping.validatePackageName(name); + if (validationResult !== JsTyping.PackageNameValidationResult.Ok) { + return false; + } + + if (this.requestedRegistry) { + return !!this.typesRegistryCache && this.typesRegistryCache.has(name); + } + + this.requestedRegistry = true; + this.send({ kind: "typesRegistry" }); + return false; + } + + installPackage(options: InstallPackageOptionsWithProjectRootPath): PromiseLike { + const rq: InstallPackageRequest = { kind: "installPackage", ...options }; + this.send(rq); + Debug.assert(this.packageInstalledPromise === undefined); + return new Promise((resolve, reject) => { + this.packageInstalledPromise = { resolve, reject }; + }); + } + private reportInstallerProcessId() { if (this.installerPidReported) { return; @@ -343,7 +371,11 @@ namespace ts.server { } onProjectClosed(p: Project): void { - this.installer.send({ projectName: p.getProjectName(), kind: "closeProject" }); + this.send({ projectName: p.getProjectName(), kind: "closeProject" }); + } + + private send(rq: TypingInstallerRequestUnion): void { + this.installer.send(rq); } enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void { @@ -359,7 +391,7 @@ namespace ts.server { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Sending request:${stringifyIndented(request)}`); } - this.installer.send(request); + this.send(request); }; const queuedRequest: QueuedOperation = { operationId, operation }; @@ -375,12 +407,26 @@ namespace ts.server { } } - private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { + private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Received response:${stringifyIndented(response)}`); } switch (response.kind) { + case EventTypesRegistry: + this.typesRegistryCache = ts.createMapFromTemplate(response.typesRegistry); + break; + case EventPackageInstalled: { + const { success, message } = response; + if (success) { + this.packageInstalledPromise.resolve({ successMessage: message }); + } + else { + this.packageInstalledPromise.reject(message); + } + this.packageInstalledPromise = undefined; + break; + } case EventInitializationFailed: { if (!this.eventSender) { diff --git a/src/server/session.ts b/src/server/session.ts index 017784530d5bf..7725a699ee273 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -411,19 +411,27 @@ namespace ts.server { this.send(ev); } - public output(info: any, cmdName: string, reqSeq = 0, errorMsg?: string) { + // For backwards-compatibility only. + public output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void { + this.doOutput(info, cmdName, reqSeq, /*success*/ !errorMsg, errorMsg); + } + + private doOutput(info: {} | undefined, cmdName: string, reqSeq: number, success: boolean, message?: string): void { const res: protocol.Response = { seq: 0, type: "response", command: cmdName, request_seq: reqSeq, - success: !errorMsg, + success, }; - if (!errorMsg) { + if (success) { res.body = info; } else { - res.message = errorMsg; + Debug.assert(info === undefined); + } + if (message) { + res.message = message; } this.send(res); } @@ -1307,7 +1315,7 @@ namespace ts.server { this.changeSeq++; // make sure no changes happen before this one is finished if (project.reloadScript(file, tempFileName)) { - this.output(undefined, CommandNames.Reload, reqSeq); + this.doOutput(/*info*/ undefined, CommandNames.Reload, reqSeq, /*success*/ true); } } @@ -1545,6 +1553,15 @@ namespace ts.server { } } + private applyCodeActionCommand(commandName: string, requestSeq: number, args: protocol.ApplyCodeActionCommandRequestArgs): void { + const { file, project } = this.getFileAndProject(args); + const output = (success: boolean, message: string) => this.doOutput({}, commandName, requestSeq, success, message); + const command = args.command as CodeActionCommand; // They should be sending back the command we sent them. + project.getLanguageService().applyCodeActionCommand(file, command).then( + ({ successMessage }) => { output(/*success*/ true, successMessage); }, + error => { output(/*success*/ false, error); }); + } + private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) { let startPosition: number = undefined, endPosition: number = undefined; if (args.startPosition !== undefined) { @@ -1567,14 +1584,12 @@ namespace ts.server { return { startPosition, endPosition }; } - private mapCodeAction(codeAction: CodeAction, scriptInfo: ScriptInfo): protocol.CodeAction { - return { - description: codeAction.description, - changes: codeAction.changes.map(change => ({ - fileName: change.fileName, - textChanges: change.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo)) - })) - }; + private mapCodeAction({ description, changes: unmappedChanges, commands }: CodeAction, scriptInfo: ScriptInfo): protocol.CodeAction { + const changes = unmappedChanges.map(change => ({ + fileName: change.fileName, + textChanges: change.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo)) + })); + return { description, changes, commands }; } private mapTextChangesToCodeEdits(project: Project, textChanges: FileTextChanges): protocol.FileCodeEdits { @@ -1660,15 +1675,15 @@ namespace ts.server { exit() { } - private notRequired() { + private notRequired(): HandlerResponse { return { responseRequired: false }; } - private requiredResponse(response: any) { + private requiredResponse(response: {}): HandlerResponse { return { response, responseRequired: true }; } - private handlers = createMapFromTemplate<(request: protocol.Request) => { response?: any, responseRequired?: boolean }>({ + private handlers = createMapFromTemplate<(request: protocol.Request) => HandlerResponse>({ [CommandNames.OpenExternalProject]: (request: protocol.OpenExternalProjectRequest) => { this.projectService.openExternalProject(request.arguments, /*suppressRefreshOfInferredProjects*/ false); // TODO: report errors @@ -1846,7 +1861,7 @@ namespace ts.server { }, [CommandNames.Configure]: (request: protocol.ConfigureRequest) => { this.projectService.setHostConfiguration(request.arguments); - this.output(undefined, CommandNames.Configure, request.seq); + this.doOutput(/*info*/ undefined, CommandNames.Configure, request.seq, /*success*/ true); return this.notRequired(); }, [CommandNames.Reload]: (request: protocol.ReloadRequest) => { @@ -1913,6 +1928,10 @@ namespace ts.server { [CommandNames.GetCodeFixesFull]: (request: protocol.CodeFixRequest) => { return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false)); }, + [CommandNames.ApplyCodeActionCommand]: (request: protocol.ApplyCodeActionCommandRequest) => { + this.applyCodeActionCommand(request.command, request.seq, request.arguments); + return this.notRequired(); // Response will come asynchronously. + }, [CommandNames.GetSupportedCodeFixes]: () => { return this.requiredResponse(this.getSupportedCodeFixes()); }, @@ -1927,7 +1946,7 @@ namespace ts.server { } }); - public addProtocolHandler(command: string, handler: (request: protocol.Request) => { response?: any, responseRequired: boolean }) { + public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) { if (this.handlers.has(command)) { throw new Error(`Protocol handler already exists for command "${command}"`); } @@ -1956,14 +1975,14 @@ namespace ts.server { } } - public executeCommand(request: protocol.Request): { response?: any, responseRequired?: boolean } { + public executeCommand(request: protocol.Request): HandlerResponse { const handler = this.handlers.get(request.command); if (handler) { return this.executeWithRequestId(request.seq, () => handler(request)); } else { this.logger.msg(`Unrecognized JSON command:${stringifyIndented(request)}`, Msg.Err); - this.output(undefined, CommandNames.Unknown, request.seq, `Unrecognized JSON command: ${request.command}`); + this.doOutput(/*info*/ undefined, CommandNames.Unknown, request.seq, /*success*/ false, `Unrecognized JSON command: ${request.command}`); return { responseRequired: false }; } } @@ -1994,25 +2013,31 @@ namespace ts.server { } if (response) { - this.output(response, request.command, request.seq); + this.doOutput(response, request.command, request.seq, /*success*/ true); } else if (responseRequired) { - this.output(undefined, request.command, request.seq, "No content available."); + this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ false, "No content available."); } } catch (err) { if (err instanceof OperationCanceledException) { // Handle cancellation exceptions - this.output({ canceled: true }, request.command, request.seq); + this.doOutput({ canceled: true }, request.command, request.seq, /*success*/ true); return; } this.logError(err, message); - this.output( - undefined, + this.doOutput( + /*info*/ undefined, request ? request.command : CommandNames.Unknown, request ? request.seq : 0, + /*success*/ false, "Error processing request. " + (err).message + "\n" + (err).stack); } } } + + export interface HandlerResponse { + response?: {}; + responseRequired?: boolean; + } } diff --git a/src/server/shared.ts b/src/server/shared.ts index 66f739a5b974a..a8a122c3327ee 100644 --- a/src/server/shared.ts +++ b/src/server/shared.ts @@ -3,6 +3,8 @@ namespace ts.server { export const ActionSet: ActionSet = "action::set"; export const ActionInvalidate: ActionInvalidate = "action::invalidate"; + export const EventTypesRegistry: EventTypesRegistry = "event::typesRegistry"; + export const EventPackageInstalled: EventPackageInstalled = "event::packageInstalled"; export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes"; export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes"; export const EventInitializationFailed: EventInitializationFailed = "event::initializationFailed"; diff --git a/src/server/types.ts b/src/server/types.ts index 4fc4356a4a97f..af5e121278eff 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -28,12 +28,14 @@ declare namespace ts.server { " __sortedArrayBrand": any; } - export interface TypingInstallerRequest { + export interface TypingInstallerRequestWithProjectName { readonly projectName: string; - readonly kind: "discover" | "closeProject"; } - export interface DiscoverTypings extends TypingInstallerRequest { + /* @internal */ + export type TypingInstallerRequestUnion = DiscoverTypings | CloseProject | TypesRegistryRequest | InstallPackageRequest; + + export interface DiscoverTypings extends TypingInstallerRequestWithProjectName { readonly fileNames: string[]; readonly projectRootPath: Path; readonly compilerOptions: CompilerOptions; @@ -43,18 +45,46 @@ declare namespace ts.server { readonly kind: "discover"; } - export interface CloseProject extends TypingInstallerRequest { + export interface CloseProject extends TypingInstallerRequestWithProjectName { readonly kind: "closeProject"; } + export interface TypesRegistryRequest { + readonly kind: "typesRegistry"; + } + + export interface InstallPackageRequest { + readonly kind: "installPackage"; + readonly fileName: Path; + readonly packageName: string; + readonly projectRootPath: Path; + } + export type ActionSet = "action::set"; export type ActionInvalidate = "action::invalidate"; + export type EventTypesRegistry = "event::typesRegistry"; + export type EventPackageInstalled = "event::packageInstalled"; export type EventBeginInstallTypes = "event::beginInstallTypes"; export type EventEndInstallTypes = "event::endInstallTypes"; export type EventInitializationFailed = "event::initializationFailed"; export interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | EventPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + } + /* @internal */ + export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse; + + /* @internal */ + export interface TypesRegistryResponse extends TypingInstallerResponse { + readonly kind: EventTypesRegistry; + readonly typesRegistry: MapLike; + } + + /* @internal */ + export interface PackageInstalledResponse extends TypingInstallerResponse { + readonly kind: EventPackageInstalled; + readonly success: boolean; + readonly message: string; } export interface InitializationFailedResponse extends TypingInstallerResponse { diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 207824616a980..ddcf85063fdda 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -1,7 +1,13 @@ /// namespace ts.server { + export interface InstallPackageOptionsWithProjectRootPath extends InstallPackageOptions { + projectRootPath: Path; + } + export interface ITypingsInstaller { + isKnownTypesPackageName(name: string): boolean; + installPackage(options: InstallPackageOptionsWithProjectRootPath): PromiseLike; enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; @@ -9,6 +15,9 @@ namespace ts.server { } export const nullTypingsInstaller: ITypingsInstaller = { + isKnownTypesPackageName: returnFalse, + // Should never be called because we never provide a types registry. + installPackage: notImplemented, enqueueInstallTypingsRequest: noop, attach: noop, onProjectClosed: noop, @@ -77,6 +86,14 @@ namespace ts.server { constructor(private readonly installer: ITypingsInstaller) { } + isKnownTypesPackageName(name: string): boolean { + return this.installer.isKnownTypesPackageName(name); + } + + installPackage(options: InstallPackageOptionsWithProjectRootPath): PromiseLike { + return this.installer.installPackage(options); + } + getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray { const typeAcquisition = project.getTypeAcquisition(); diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index d32dd2a4b5f76..2a1036010a733 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -53,7 +53,7 @@ namespace ts.server.typingsInstaller { } try { const content = JSON.parse(host.readFile(typesRegistryFilePath)); - return createMapFromTemplate(content.entries); + return createMapFromTemplate(content.entries); } catch (e) { if (log.isEnabled()) { @@ -79,7 +79,7 @@ namespace ts.server.typingsInstaller { private readonly npmPath: string; readonly typesRegistry: Map; - private delayedInitializationError: InitializationFailedResponse; + private delayedInitializationError: InitializationFailedResponse | undefined; constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, typesMapLocation: string, npmLocation: string | undefined, throttleLimit: number, log: Log) { super( @@ -127,7 +127,7 @@ namespace ts.server.typingsInstaller { } listen() { - process.on("message", (req: DiscoverTypings | CloseProject) => { + process.on("message", (req: TypingInstallerRequestUnion) => { if (this.delayedInitializationError) { // report initializationFailed error this.sendResponse(this.delayedInitializationError); @@ -139,11 +139,39 @@ namespace ts.server.typingsInstaller { break; case "closeProject": this.closeProject(req); + break; + case "typesRegistry": { + const typesRegistry: { [key: string]: void } = {}; + this.typesRegistry.forEach((value, key) => { + typesRegistry[key] = value; + }); + const response: TypesRegistryResponse = { kind: EventTypesRegistry, typesRegistry }; + this.sendResponse(response); + break; + } + case "installPackage": { + const { fileName, packageName, projectRootPath } = req; + const cwd = getDirectoryOfPackageJson(fileName, this.installTypingHost) || projectRootPath; + if (cwd) { + this.installWorker(-1, [packageName], cwd, success => { + const message = success ? `Package ${packageName} installed.` : `There was an error installing ${packageName}.`; + const response: PackageInstalledResponse = { kind: EventPackageInstalled, success, message }; + this.sendResponse(response); + }); + } + else { + const response: PackageInstalledResponse = { kind: EventPackageInstalled, success: false, message: "Could not determine a project root path." }; + this.sendResponse(response); + } + break; + } + default: + Debug.assertNever(req); } }); } - protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { + protected sendResponse(response: TypingInstallerResponseUnion) { if (this.log.isEnabled()) { this.log.writeLine(`Sending response:\n ${JSON.stringify(response)}`); } @@ -153,11 +181,11 @@ namespace ts.server.typingsInstaller { } } - protected installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + protected installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { if (this.log.isEnabled()) { - this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(args)}'.`); + this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } - const command = `${this.npmPath} install --ignore-scripts ${args.join(" ")} --save-dev --user-agent="typesInstaller/${version}"`; + const command = `${this.npmPath} install --ignore-scripts ${packageNames.join(" ")} --save-dev --user-agent="typesInstaller/${version}"`; const start = Date.now(); const hasError = this.execSyncAndLog(command, { cwd }); if (this.log.isEnabled()) { @@ -186,6 +214,14 @@ namespace ts.server.typingsInstaller { } } + function getDirectoryOfPackageJson(fileName: string, host: InstallTypingHost): string | undefined { + return forEachAncestorDirectory(getDirectoryPath(fileName), directory => { + if (host.fileExists(combinePaths(directory, "package.json"))) { + return directory; + } + }); + } + const logFilePath = findArgument(server.Arguments.LogFile); const globalTypingsCacheLocation = findArgument(server.Arguments.GlobalCacheLocation); const typingSafeListLocation = findArgument(server.Arguments.TypingSafeListLocation); diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 3eae0755747b7..26e7781b4406e 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -32,50 +32,11 @@ namespace ts.server.typingsInstaller { } } - export enum PackageNameValidationResult { - Ok, - ScopedPackagesNotSupported, - EmptyName, - NameTooLong, - NameStartsWithDot, - NameStartsWithUnderscore, - NameContainsNonURISafeCharacters - } - - - export const MaxPackageNameLength = 214; - /** - * Validates package name using rules defined at https://docs.npmjs.com/files/package.json - */ - export function validatePackageName(packageName: string): PackageNameValidationResult { - if (!packageName) { - return PackageNameValidationResult.EmptyName; - } - if (packageName.length > MaxPackageNameLength) { - return PackageNameValidationResult.NameTooLong; - } - if (packageName.charCodeAt(0) === CharacterCodes.dot) { - return PackageNameValidationResult.NameStartsWithDot; - } - if (packageName.charCodeAt(0) === CharacterCodes._) { - return PackageNameValidationResult.NameStartsWithUnderscore; - } - // check if name is scope package like: starts with @ and has one '/' in the middle - // scoped packages are not currently supported - // TODO: when support will be added we'll need to split and check both scope and package name - if (/^@[^/]+\/[^/]+$/.test(packageName)) { - return PackageNameValidationResult.ScopedPackagesNotSupported; - } - if (encodeURIComponent(packageName) !== packageName) { - return PackageNameValidationResult.NameContainsNonURISafeCharacters; - } - return PackageNameValidationResult.Ok; - } export type RequestCompletedAction = (success: boolean) => void; interface PendingRequest { requestId: number; - args: string[]; + packageNames: string[]; cwd: string; onRequestCompleted: RequestCompletedAction; } @@ -255,8 +216,8 @@ namespace ts.server.typingsInstaller { if (this.missingTypingsSet.get(typing) || this.packageNameToTypingLocation.get(typing)) { continue; } - const validationResult = validatePackageName(typing); - if (validationResult === PackageNameValidationResult.Ok) { + const validationResult = JsTyping.validatePackageName(typing); + if (validationResult === JsTyping.PackageNameValidationResult.Ok) { if (this.typesRegistry.has(typing)) { result.push(typing); } @@ -270,26 +231,7 @@ namespace ts.server.typingsInstaller { // add typing name to missing set so we won't process it again this.missingTypingsSet.set(typing, true); if (this.log.isEnabled()) { - switch (validationResult) { - case PackageNameValidationResult.EmptyName: - this.log.writeLine(`Package name '${typing}' cannot be empty`); - break; - case PackageNameValidationResult.NameTooLong: - this.log.writeLine(`Package name '${typing}' should be less than ${MaxPackageNameLength} characters`); - break; - case PackageNameValidationResult.NameStartsWithDot: - this.log.writeLine(`Package name '${typing}' cannot start with '.'`); - break; - case PackageNameValidationResult.NameStartsWithUnderscore: - this.log.writeLine(`Package name '${typing}' cannot start with '_'`); - break; - case PackageNameValidationResult.ScopedPackagesNotSupported: - this.log.writeLine(`Package '${typing}' is scoped and currently is not supported`); - break; - case PackageNameValidationResult.NameContainsNonURISafeCharacters: - this.log.writeLine(`Package name '${typing}' contains non URI safe characters`); - break; - } + this.log.writeLine(JsTyping.renderPackageNameValidationFailure(validationResult, typing)); } } } @@ -430,8 +372,8 @@ namespace ts.server.typingsInstaller { }; } - private installTypingsAsync(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { - this.pendingRunRequests.unshift({ requestId, args, cwd, onRequestCompleted }); + private installTypingsAsync(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { + this.pendingRunRequests.unshift({ requestId, packageNames, cwd, onRequestCompleted }); this.executeWithThrottling(); } @@ -439,7 +381,7 @@ namespace ts.server.typingsInstaller { while (this.inFlightRequestCount < this.throttleLimit && this.pendingRunRequests.length) { this.inFlightRequestCount++; const request = this.pendingRunRequests.pop(); - this.installWorker(request.requestId, request.args, request.cwd, ok => { + this.installWorker(request.requestId, request.packageNames, request.cwd, ok => { this.inFlightRequestCount--; request.onRequestCompleted(ok); this.executeWithThrottling(); @@ -447,7 +389,7 @@ namespace ts.server.typingsInstaller { } } - protected abstract installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; + protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void; } diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts new file mode 100644 index 0000000000000..b7fde9d917ef9 --- /dev/null +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -0,0 +1,35 @@ +/* @internal */ +namespace ts.codefix { + registerCodeFix({ + errorCodes: [ + Diagnostics.Cannot_find_module_0.code, + Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type.code, + ], + getCodeActions: context => { + const { sourceFile, span: { start } } = context; + const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); + if (!isStringLiteral(token)) { + throw Debug.fail(); // These errors should only happen on the module name. + } + + const action = tryGetCodeActionForInstallPackageTypes(context.host, token.text); + return action && [action]; + }, + }); + + export function tryGetCodeActionForInstallPackageTypes(host: LanguageServiceHost, moduleName: string): CodeAction | undefined { + const { packageName } = getPackageName(moduleName); + + if (!host.isKnownTypesPackageName(packageName)) { + // If !registry, registry not available yet, can't do anything. + return undefined; + } + + const typesPackageName = getTypesPackageName(packageName); + return { + description: `Install '${typesPackageName}'`, + changes: [], + commands: [{ type: "install package", packageName: typesPackageName }], + }; + } +} diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts index 7ee0aaa679973..5b1ee8ec8572c 100644 --- a/src/services/codefixes/fixes.ts +++ b/src/services/codefixes/fixes.ts @@ -3,6 +3,7 @@ /// /// /// +/// /// /// /// diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index f1859a90b98fa..572858dd2fd0d 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -246,4 +246,65 @@ namespace ts.JsTyping { } } + + export const enum PackageNameValidationResult { + Ok, + ScopedPackagesNotSupported, + EmptyName, + NameTooLong, + NameStartsWithDot, + NameStartsWithUnderscore, + NameContainsNonURISafeCharacters + } + + const MaxPackageNameLength = 214; + + /** + * Validates package name using rules defined at https://docs.npmjs.com/files/package.json + */ + export function validatePackageName(packageName: string): PackageNameValidationResult { + if (!packageName) { + return PackageNameValidationResult.EmptyName; + } + if (packageName.length > MaxPackageNameLength) { + return PackageNameValidationResult.NameTooLong; + } + if (packageName.charCodeAt(0) === CharacterCodes.dot) { + return PackageNameValidationResult.NameStartsWithDot; + } + if (packageName.charCodeAt(0) === CharacterCodes._) { + return PackageNameValidationResult.NameStartsWithUnderscore; + } + // check if name is scope package like: starts with @ and has one '/' in the middle + // scoped packages are not currently supported + // TODO: when support will be added we'll need to split and check both scope and package name + if (/^@[^/]+\/[^/]+$/.test(packageName)) { + return PackageNameValidationResult.ScopedPackagesNotSupported; + } + if (encodeURIComponent(packageName) !== packageName) { + return PackageNameValidationResult.NameContainsNonURISafeCharacters; + } + return PackageNameValidationResult.Ok; + } + + export function renderPackageNameValidationFailure(result: PackageNameValidationResult, typing: string): string { + switch (result) { + case PackageNameValidationResult.EmptyName: + return `Package name '${typing}' cannot be empty`; + case PackageNameValidationResult.NameTooLong: + return `Package name '${typing}' should be less than ${MaxPackageNameLength} characters`; + case PackageNameValidationResult.NameStartsWithDot: + return `Package name '${typing}' cannot start with '.'`; + case PackageNameValidationResult.NameStartsWithUnderscore: + return `Package name '${typing}' cannot start with '_'`; + case PackageNameValidationResult.ScopedPackagesNotSupported: + return `Package '${typing}' is scoped and currently is not supported`; + case PackageNameValidationResult.NameContainsNonURISafeCharacters: + return `Package name '${typing}' contains non URI safe characters`; + case PackageNameValidationResult.Ok: + throw Debug.fail(); // Shouldn't have called this. + default: + Debug.assertNever(result); + } + } } diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index b338882e6db68..e0a1924793976 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -19,6 +19,7 @@ namespace ts { startPosition: number; endPosition?: number; program: Program; + host: LanguageServiceHost; cancellationToken?: CancellationToken; } diff --git a/src/services/refactors/installTypesForPackage.ts b/src/services/refactors/installTypesForPackage.ts new file mode 100644 index 0000000000000..ded4a1d47afaf --- /dev/null +++ b/src/services/refactors/installTypesForPackage.ts @@ -0,0 +1,63 @@ +/* @internal */ +namespace ts.refactor.installTypesForPackage { + const actionName = "install"; + + const installTypesForPackage: Refactor = { + name: "Install missing types package", + description: "Install missing types package", + getEditsForAction, + getAvailableActions, + }; + + registerRefactor(installTypesForPackage); + + function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { + if (context.program.getCompilerOptions().noImplicitAny) { + // Then it will be available via `fixCannotFindModule`. + return undefined; + } + + const action = getAction(context); + return action && [ + { + name: installTypesForPackage.name, + description: installTypesForPackage.description, + actions: [ + { + description: action.description, + name: actionName, + }, + ], + }, + ]; + } + + function getEditsForAction(context: RefactorContext, _actionName: string): RefactorEditInfo | undefined { + Debug.assertEqual(actionName, _actionName); + const action = getAction(context)!; // Should be defined if we said there was an action available. + return { + edits: [], + renameFilename: undefined, + renameLocation: undefined, + commands: action.commands, + }; + } + + function getAction(context: RefactorContext): CodeAction | undefined { + const { file, startPosition } = context; + const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); + if (isStringLiteral(node) && isModuleIdentifier(node) && getResolvedModule(file, node.text) === undefined) { + return codefix.tryGetCodeActionForInstallPackageTypes(context.host, node.text); + } + } + + function isModuleIdentifier(node: StringLiteral): boolean { + switch (node.parent.kind) { + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExternalModuleReference: + return true; + default: + return false; + } + } +} \ No newline at end of file diff --git a/src/services/refactors/refactors.ts b/src/services/refactors/refactors.ts index 21aeda7ae5278..f4b56422a89bd 100644 --- a/src/services/refactors/refactors.ts +++ b/src/services/refactors/refactors.ts @@ -1,3 +1,4 @@ /// /// /// +/// diff --git a/src/services/services.ts b/src/services/services.ts index 0399ca1658e9d..a5c9c1d353a18 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1763,6 +1763,19 @@ namespace ts { }); } + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): PromiseLike { + fileName = toPath(fileName, currentDirectory, getCanonicalFileName); + switch (action.type) { + case "install package": + return host.installPackage + ? host.installPackage({ fileName, packageName: action.packageName }) + : Promise.reject("Host does not implement `installPackage`"); + default: + Debug.fail(); + // TODO: Debug.assertNever(action); will only work if there is more than one type. + } + } + function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { return JsDoc.getDocCommentTemplateAtPosition(getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); } @@ -1972,8 +1985,9 @@ namespace ts { endPosition, program: getProgram(), newLineCharacter: formatOptions ? formatOptions.newLineCharacter : host.getNewLine(), + host, rulesProvider: getRuleProvider(formatOptions), - cancellationToken + cancellationToken, }; } @@ -2035,6 +2049,7 @@ namespace ts { isValidBraceCompletionAtPosition, getSpanOfEnclosingComment, getCodeFixesAtPosition, + applyCodeActionCommand, getEmitOutput, getNonBoundSourceFile, getSourceFile, diff --git a/src/services/types.ts b/src/services/types.ts index 7bf4a909a7a34..7ec559be92283 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -145,10 +145,15 @@ namespace ts { isCancellationRequested(): boolean; } + export interface InstallPackageOptions { + fileName: Path; + packageName: string; + } + // // Public interface of the host of a language service instance. // - export interface LanguageServiceHost { + export interface LanguageServiceHost extends GetEffectiveTypeRootsHost { getCompilationSettings(): CompilerOptions; getNewLine?(): string; getProjectVersion?(): string; @@ -158,7 +163,6 @@ namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; - getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; @@ -187,7 +191,6 @@ namespace ts { resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean; - directoryExists?(directoryName: string): boolean; /* * getDirectories is also required for full import and type reference completions. Without it defined, certain @@ -199,6 +202,9 @@ namespace ts { * Gets a set of custom transformers to use during emit. */ getCustomTransformers?(): CustomTransformers | undefined; + + isKnownTypesPackageName?(name: string): boolean; + installPackage?(options: InstallPackageOptions): PromiseLike; } // @@ -276,6 +282,7 @@ namespace ts { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; + applyCodeActionCommand(fileName: string, action: CodeActionCommand): PromiseLike; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; @@ -295,6 +302,10 @@ namespace ts { dispose(): void; } + export interface ApplyCodeActionCommandResult { + successMessage: string; + } + export interface Classifications { spans: number[]; endOfLineState: EndOfLineState; @@ -367,6 +378,20 @@ namespace ts { description: string; /** Text changes to apply to each file as part of the code action */ changes: FileTextChanges[]; + /** + * If the user accepts the code fix, the editor should send the action back in a `applyAction` request. + * This allows the language service to have side effects (e.g. installing dependencies) upon a code fix. + */ + commands?: CodeActionCommand[]; + } + + // Publicly, this type is just `{}`. Internally it is a union of all the actions we use. + // See `commands?: {}[]` in protocol.ts + export type CodeActionCommand = InstallPackageAction; + + export interface InstallPackageAction { + /* @internal */ type: "install package"; + /* @internal */ packageName: string; } /** @@ -420,6 +445,7 @@ namespace ts { edits: FileTextChanges[]; renameFilename: string | undefined; renameLocation: number | undefined; + commands?: CodeActionCommand[]; } export interface TextInsertion { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 716a4188db25b..2b116eb1cd05c 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1,3 +1,12 @@ +/* @internal */ // Don't expose that we use this +// Based on lib.es6.d.ts +interface PromiseConstructor { + new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + reject(reason: any): Promise; +} +/* @internal */ +declare var Promise: PromiseConstructor; + // These utilities are common to multiple language service features. /* @internal */ namespace ts { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 56c7fa5f98c44..15eca3da329f4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3869,7 +3869,11 @@ declare namespace ts { interface HostCancellationToken { isCancellationRequested(): boolean; } - interface LanguageServiceHost { + interface InstallPackageOptions { + fileName: Path; + packageName: string; + } + interface LanguageServiceHost extends GetEffectiveTypeRootsHost { getCompilationSettings(): CompilerOptions; getNewLine?(): string; getProjectVersion?(): string; @@ -3879,7 +3883,6 @@ declare namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; - getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; @@ -3891,12 +3894,13 @@ declare namespace ts { getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; - directoryExists?(directoryName: string): boolean; getDirectories?(directoryName: string): string[]; /** * Gets a set of custom transformers to use during emit. */ getCustomTransformers?(): CustomTransformers | undefined; + isKnownTypesPackageName?(name: string): boolean; + installPackage?(options: InstallPackageOptions): PromiseLike; } interface LanguageService { cleanupSemanticCache(): void; @@ -3944,6 +3948,7 @@ declare namespace ts { isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; + applyCodeActionCommand(fileName: string, action: CodeActionCommand): PromiseLike; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; @@ -3951,6 +3956,9 @@ declare namespace ts { getProgram(): Program; dispose(): void; } + interface ApplyCodeActionCommandResult { + successMessage: string; + } interface Classifications { spans: number[]; endOfLineState: EndOfLineState; @@ -4015,6 +4023,14 @@ declare namespace ts { description: string; /** Text changes to apply to each file as part of the code action */ changes: FileTextChanges[]; + /** + * If the user accepts the code fix, the editor should send the action back in a `applyAction` request. + * This allows the language service to have side effects (e.g. installing dependencies) upon a code fix. + */ + commands?: CodeActionCommand[]; + } + type CodeActionCommand = InstallPackageAction; + interface InstallPackageAction { } /** * A set of one or more available refactoring actions, grouped under a parent refactoring. @@ -4063,6 +4079,7 @@ declare namespace ts { edits: FileTextChanges[]; renameFilename: string | undefined; renameLocation: number | undefined; + commands?: CodeActionCommand[]; } interface TextInsertion { newText: string; @@ -4633,11 +4650,10 @@ declare namespace ts.server { interface SortedReadonlyArray extends ReadonlyArray { " __sortedArrayBrand": any; } - interface TypingInstallerRequest { + interface TypingInstallerRequestWithProjectName { readonly projectName: string; - readonly kind: "discover" | "closeProject"; } - interface DiscoverTypings extends TypingInstallerRequest { + interface DiscoverTypings extends TypingInstallerRequestWithProjectName { readonly fileNames: string[]; readonly projectRootPath: Path; readonly compilerOptions: CompilerOptions; @@ -4646,16 +4662,27 @@ declare namespace ts.server { readonly cachePath?: string; readonly kind: "discover"; } - interface CloseProject extends TypingInstallerRequest { + interface CloseProject extends TypingInstallerRequestWithProjectName { readonly kind: "closeProject"; } + interface TypesRegistryRequest { + readonly kind: "typesRegistry"; + } + interface InstallPackageRequest { + readonly kind: "installPackage"; + readonly fileName: Path; + readonly packageName: string; + readonly projectRootPath: Path; + } type ActionSet = "action::set"; type ActionInvalidate = "action::invalidate"; + type EventTypesRegistry = "event::typesRegistry"; + type EventPackageInstalled = "event::packageInstalled"; type EventBeginInstallTypes = "event::beginInstallTypes"; type EventEndInstallTypes = "event::endInstallTypes"; type EventInitializationFailed = "event::initializationFailed"; interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | EventPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; } interface InitializationFailedResponse extends TypingInstallerResponse { readonly kind: EventInitializationFailed; @@ -4691,6 +4718,8 @@ declare namespace ts.server { declare namespace ts.server { const ActionSet: ActionSet; const ActionInvalidate: ActionInvalidate; + const EventTypesRegistry: EventTypesRegistry; + const EventPackageInstalled: EventPackageInstalled; const EventBeginInstallTypes: EventBeginInstallTypes; const EventEndInstallTypes: EventEndInstallTypes; const EventInitializationFailed: EventInitializationFailed; @@ -4828,6 +4857,7 @@ declare namespace ts.server.protocol { DocCommentTemplate = "docCommentTemplate", CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects", GetCodeFixes = "getCodeFixes", + ApplyCodeActionCommand = "applyCodeActionCommand", GetSupportedCodeFixes = "getSupportedCodeFixes", GetApplicableRefactors = "getApplicableRefactors", GetEditsForRefactor = "getEditsForRefactor", @@ -4849,6 +4879,7 @@ declare namespace ts.server.protocol { * Client-initiated request message */ interface Request extends Message { + type: "request"; /** * The command to execute */ @@ -4868,6 +4899,7 @@ declare namespace ts.server.protocol { * Server-initiated event message */ interface Event extends Message { + type: "event"; /** * Name of event */ @@ -4881,6 +4913,7 @@ declare namespace ts.server.protocol { * Response by server to client request message. */ interface Response extends Message { + type: "response"; /** * Sequence number of the request message. */ @@ -4894,7 +4927,8 @@ declare namespace ts.server.protocol { */ command: string; /** - * Contains error message if success === false. + * If success === false, this should always be provided. + * Otherwise, may (or may not) contain a success message. */ message?: string; /** @@ -5170,6 +5204,12 @@ declare namespace ts.server.protocol { command: CommandTypes.GetCodeFixes; arguments: CodeFixRequestArgs; } + interface ApplyCodeActionCommandRequest extends Request { + command: CommandTypes.ApplyCodeActionCommand; + arguments: ApplyCodeActionCommandRequestArgs; + } + interface ApplyCodeActionCommandResponse extends Response { + } interface FileRangeRequestArgs extends FileRequestArgs { /** * The line number for the request (1-based). @@ -5197,6 +5237,9 @@ declare namespace ts.server.protocol { */ errorCodes?: number[]; } + interface ApplyCodeActionCommandRequestArgs extends FileRequestArgs { + command: {}; + } /** * Response for GetCodeFixes request. */ @@ -5935,6 +5978,8 @@ declare namespace ts.server.protocol { description: string; /** Text changes to apply to each file as part of the code action */ changes: FileCodeEdits[]; + /** A command is an opaque object that should be passed to `ApplyCodeActionCommandRequestArgs` without modification. */ + commands?: {}[]; } /** * Format and format on key response message. @@ -6852,6 +6897,7 @@ declare namespace ts.server { send(msg: protocol.Message): void; event(info: T, eventName: string): void; output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void; + private doOutput(info, cmdName, reqSeq, success, message?); private semanticCheck(file, project); private syntacticCheck(file, project); private updateErrorCheck(next, checkList, ms, requireOpen?); @@ -6927,8 +6973,9 @@ declare namespace ts.server { private getApplicableRefactors(args); private getEditsForRefactor(args, simplifiedResult); private getCodeFixes(args, simplifiedResult); + private applyCodeActionCommand(commandName, requestSeq, args); private getStartAndEndPosition(args, scriptInfo); - private mapCodeAction(codeAction, scriptInfo); + private mapCodeAction({description, changes: unmappedChanges, commands}, scriptInfo); private mapTextChangesToCodeEdits(project, textChanges); private convertTextChangeToCodeEdit(change, scriptInfo); private getBraceMatching(args, simplifiedResult); @@ -6938,19 +6985,17 @@ declare namespace ts.server { private notRequired(); private requiredResponse(response); private handlers; - addProtocolHandler(command: string, handler: (request: protocol.Request) => { - response?: any; - responseRequired: boolean; - }): void; + addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse): void; private setCurrentRequest(requestId); private resetCurrentRequest(requestId); executeWithRequestId(requestId: number, f: () => T): T; - executeCommand(request: protocol.Request): { - response?: any; - responseRequired?: boolean; - }; + executeCommand(request: protocol.Request): HandlerResponse; onMessage(message: string): void; } + interface HandlerResponse { + response?: {}; + responseRequired?: boolean; + } } declare namespace ts.server { class ScriptInfo { @@ -7015,7 +7060,12 @@ declare namespace ts { function updateWatchingWildcardDirectories(existingWatchedForWildcards: Map, wildcardDirectories: Map, watchDirectory: (directory: string, flags: WatchDirectoryFlags) => FileWatcher): void; } declare namespace ts.server { + interface InstallPackageOptionsWithProjectRootPath extends InstallPackageOptions { + projectRootPath: Path; + } interface ITypingsInstaller { + isKnownTypesPackageName(name: string): boolean; + installPackage(options: InstallPackageOptionsWithProjectRootPath): PromiseLike; enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; @@ -7026,6 +7076,8 @@ declare namespace ts.server { private readonly installer; private readonly perProjectCache; constructor(installer: ITypingsInstaller); + isKnownTypesPackageName(name: string): boolean; + installPackage(options: InstallPackageOptionsWithProjectRootPath): PromiseLike; getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray; updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]): void; deleteTypingsForProject(projectName: string): void; @@ -7120,6 +7172,9 @@ declare namespace ts.server { isJsOnlyProject(): boolean; getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap; static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; + isKnownTypesPackageName(name: string): boolean; + installPackage(options: InstallPackageOptions): PromiseLike; + private readonly typingsCache; getCompilationSettings(): CompilerOptions; getCompilerOptions(): CompilerOptions; getNewLine(): string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2668a25bcfcd2..f3180b9d1069c 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3869,7 +3869,11 @@ declare namespace ts { interface HostCancellationToken { isCancellationRequested(): boolean; } - interface LanguageServiceHost { + interface InstallPackageOptions { + fileName: Path; + packageName: string; + } + interface LanguageServiceHost extends GetEffectiveTypeRootsHost { getCompilationSettings(): CompilerOptions; getNewLine?(): string; getProjectVersion?(): string; @@ -3879,7 +3883,6 @@ declare namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; - getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; @@ -3891,12 +3894,13 @@ declare namespace ts { getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; - directoryExists?(directoryName: string): boolean; getDirectories?(directoryName: string): string[]; /** * Gets a set of custom transformers to use during emit. */ getCustomTransformers?(): CustomTransformers | undefined; + isKnownTypesPackageName?(name: string): boolean; + installPackage?(options: InstallPackageOptions): PromiseLike; } interface LanguageService { cleanupSemanticCache(): void; @@ -3944,6 +3948,7 @@ declare namespace ts { isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; + applyCodeActionCommand(fileName: string, action: CodeActionCommand): PromiseLike; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; @@ -3951,6 +3956,9 @@ declare namespace ts { getProgram(): Program; dispose(): void; } + interface ApplyCodeActionCommandResult { + successMessage: string; + } interface Classifications { spans: number[]; endOfLineState: EndOfLineState; @@ -4015,6 +4023,14 @@ declare namespace ts { description: string; /** Text changes to apply to each file as part of the code action */ changes: FileTextChanges[]; + /** + * If the user accepts the code fix, the editor should send the action back in a `applyAction` request. + * This allows the language service to have side effects (e.g. installing dependencies) upon a code fix. + */ + commands?: CodeActionCommand[]; + } + type CodeActionCommand = InstallPackageAction; + interface InstallPackageAction { } /** * A set of one or more available refactoring actions, grouped under a parent refactoring. @@ -4063,6 +4079,7 @@ declare namespace ts { edits: FileTextChanges[]; renameFilename: string | undefined; renameLocation: number | undefined; + commands?: CodeActionCommand[]; } interface TextInsertion { newText: string; diff --git a/tests/cases/fourslash/codeFixCannotFindModule.ts b/tests/cases/fourslash/codeFixCannotFindModule.ts new file mode 100644 index 0000000000000..96e5c201644d1 --- /dev/null +++ b/tests/cases/fourslash/codeFixCannotFindModule.ts @@ -0,0 +1,15 @@ +/// + +////import * as abs from "abs"; + +test.setTypesRegistry({ + "abs": undefined, +}); + +verify.codeFixAvailable([{ + description: "Install '@types/abs'", + commands: [{ + type: "install package", + packageName: "@types/abs", + }], +}]); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index e1d9607de8aaf..a7c54b5dda649 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -118,6 +118,7 @@ declare namespace FourSlashInterface { rangesByText(): ts.Map; markerByName(s: string): Marker; symbolsInScope(range: Range): any[]; + setTypesRegistry(map: { [key: string]: void }): void; } class goTo { marker(name?: string | Marker): void; @@ -169,12 +170,17 @@ declare namespace FourSlashInterface { errorCode?: number, index?: number, }); - codeFixAvailable(): void; + codeFixAvailable(options: Array<{ description: string, actions: Array<{ type: string, data: {} }> }>): void; applicableRefactorAvailableAtMarker(markerName: string): void; codeFixDiagnosticsAvailableAtMarkers(markerNames: string[], diagnosticCode?: number): void; applicableRefactorAvailableForRange(): void; - refactorAvailable(name: string, actionName?: string); + refactorAvailable(name: string, actionName?: string): void; + refactor(options: { + name: string; + actionName: string; + refactors: any[]; + }): void; } class verify extends verifyNegatable { assertHasRanges(ranges: Range[]): void; @@ -277,6 +283,7 @@ declare namespace FourSlashInterface { fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: FormatCodeOptions): void; rangeIs(expectedText: string, includeWhiteSpace?: boolean): void; fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: FormatCodeOptions): void; + getAndApplyCodeFix(errorCode?: number, index?: number): void; importFixAtPosition(expectedTextArray: string[], errorCode?: number): void; navigationBar(json: any, options?: { checkSpans?: boolean }): void; diff --git a/tests/cases/fourslash/refactorInstallTypesForPackage.ts b/tests/cases/fourslash/refactorInstallTypesForPackage.ts new file mode 100644 index 0000000000000..edcdc2ba6e0c9 --- /dev/null +++ b/tests/cases/fourslash/refactorInstallTypesForPackage.ts @@ -0,0 +1,25 @@ +/// + +////import * as abs from "/*a*/abs/subModule/*b*/"; + +test.setTypesRegistry({ + "abs": undefined, +}); + +goTo.select("a", "b"); +verify.refactor({ + name: "Install missing types package", + actionName: "install", + refactors: [ + { + name: "Install missing types package", + description: "Install missing types package", + actions: [ + { + description: "Install '@types/abs'", + name: "install", + } + ] + } + ], +}); diff --git a/tests/cases/fourslash/refactorInstallTypesForPackage_importEquals.ts b/tests/cases/fourslash/refactorInstallTypesForPackage_importEquals.ts new file mode 100644 index 0000000000000..18793e4b353dd --- /dev/null +++ b/tests/cases/fourslash/refactorInstallTypesForPackage_importEquals.ts @@ -0,0 +1,25 @@ +/// + +////import abs = require("/*a*/abs/subModule/*b*/"); + +test.setTypesRegistry({ + "abs": undefined, +}); + +goTo.select("a", "b"); +verify.refactor({ + name: "Install missing types package", + actionName: "install", + refactors: [ + { + name: "Install missing types package", + description: "Install missing types package", + actions: [ + { + description: "Install '@types/abs'", + name: "install", + } + ] + } + ], +}); From 2cc4f537afff23c1f7a9d226c93cb52c75f85a46 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Oct 2017 15:41:16 -0700 Subject: [PATCH 200/246] This wasnt required before... (#19262) --- src/harness/compilerRunner.ts | 2 +- src/harness/projectsRunner.ts | 2 +- src/harness/rwcRunner.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 79695639fd8d0..a567c1c9e384e 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -48,7 +48,7 @@ class CompilerBaselineRunner extends RunnerBase { } public checkTestCodeOutput(fileName: string) { - describe("compiler tests for " + fileName, () => { + describe(`${this.testSuiteName} tests for ${fileName}`, () => { // 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; diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index ceab3ae8f3b82..cc68f8625f43f 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -443,7 +443,7 @@ class ProjectRunner extends RunnerBase { const name = "Compiling project for " + testCase.scenario + ": testcase " + testCaseFileName; - describe("Projects tests", () => { + describe("projects tests", () => { describe(name, () => { function verifyCompilerResults(moduleKind: ts.ModuleKind) { let compilerResult: BatchCompileProjectTestCaseResult; diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index eba845d44ec12..8fe97bb7e1209 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -26,7 +26,7 @@ namespace RWC { } export function runRWCTest(jsonPath: string) { - describe("Testing a RWC project: " + jsonPath, () => { + describe("Testing a rwc project: " + jsonPath, () => { let inputFiles: Harness.Compiler.TestFile[] = []; let otherFiles: Harness.Compiler.TestFile[] = []; let tsconfigFiles: Harness.Compiler.TestFile[] = []; @@ -266,6 +266,7 @@ class RWCRunner extends RunnerBase { public initializeTests(): void { // Read in and evaluate the test list const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); + for (let i = 0; i < testList.length; i++) { this.runTest(testList[i]); } From 64fc495234a3b8b3f7897041dd69c35ad8983a62 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 Oct 2017 16:33:52 -0700 Subject: [PATCH 201/246] Collapse jsdoc annotation refactors to one Previously there were two, and two always fired. --- .../refactors/annotateWithTypeFromJSDoc.ts | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 60c0517f68113..29da66f697441 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -5,16 +5,9 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { const annotateTypeFromJSDoc: Refactor = { name: "Annotate with type from JSDoc", description: Diagnostics.Annotate_with_type_from_JSDoc.message, - getEditsForAction: getEditsForAnnotation, + getEditsForAction, getAvailableActions }; - const annotateFunctionFromJSDoc: Refactor = { - name: "Annotate with types from JSDoc", - description: Diagnostics.Annotate_with_types_from_JSDoc.message, - getEditsForAction: getEditsForFunctionAnnotation, - getAvailableActions - }; - type DeclarationWithType = | FunctionLikeDeclaration | VariableDeclaration @@ -23,7 +16,6 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { | PropertyDeclaration; registerRefactor(annotateTypeFromJSDoc); - registerRefactor(annotateFunctionFromJSDoc); function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { if (isInJavaScriptFile(context.file)) { @@ -37,16 +29,13 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } const jsdocType = getJSDocType(decl); const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); - const refactor = (isFunctionWithJSDoc || jsdocType && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc : - jsdocType ? annotateTypeFromJSDoc : - undefined; - if (refactor) { + if (isFunctionWithJSDoc || jsdocType) { return [{ - name: refactor.name, - description: refactor.description, + name: annotateTypeFromJSDoc.name, + description: annotateTypeFromJSDoc.description, actions: [ { - description: refactor.description, + description: annotateTypeFromJSDoc.description, name: actionName } ] @@ -54,11 +43,29 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } } - function getEditsForAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { + function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined { if (actionName !== action) { return Debug.fail(`actionName !== action: ${actionName} !== ${action}`); } + const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); + const decl = findAncestor(node, isDeclarationWithType); + if (!decl || decl.type) { + return undefined; + } + const jsdocType = getJSDocType(decl); + const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); + if (isFunctionWithJSDoc || jsdocType && decl.kind === SyntaxKind.Parameter) { + return getEditsForFunctionAnnotation(context); + } + else if (jsdocType) { + return getEditsForAnnotation(context); + } + else { + Debug.assert(!!refactor, "No applicable refactor found."); + } + } + function getEditsForAnnotation(context: RefactorContext): RefactorEditInfo | undefined { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(token, isDeclarationWithType); @@ -78,11 +85,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { }; } - function getEditsForFunctionAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined { - if (actionName !== action) { - return Debug.fail(`actionName !== action: ${actionName} !== ${action}`); - } - + function getEditsForFunctionAnnotation(context: RefactorContext): RefactorEditInfo | undefined { const sourceFile = context.file; const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false); const decl = findAncestor(token, isFunctionLikeDeclaration); From e962e4abfbedd071945c7e5ec0c9e5a9305951df Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 17 Oct 2017 16:35:28 -0700 Subject: [PATCH 202/246] Update baselines --- tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts | 2 +- tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts index 0553a411c2e6f..f90c61c33d94d 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts index aaa7aaefa5b7e..f0ab5f3013e5b 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('2', * @param {?} x * @returns {number} */ -var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts index e541bad4e4f29..fc9b7c2a17eae 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts @@ -15,4 +15,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', */ m(x): any[] { } -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts index a47c090cd17e9..da147548b2775 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `class C { /** @return {number} */ get c(): number { return 12; } -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts index 13b4591de4764..5020d0f11cf1b 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `/** @return {number} */ function f(): number { return 12; -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts index c316430b71803..1389e800f5a71 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts @@ -27,4 +27,4 @@ verify.fileAfterApplyingRefactorAtMarker('9', * @param {promise} zeta */ function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta: Promise) { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts index ed3180d3bd8be..ec26a9d1de7bb 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts @@ -14,5 +14,5 @@ verify.fileAfterApplyingRefactorAtMarker('1', */ constructor(x: number) { } -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts index 9cfcb5c2471f4..10d3192583dac 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts @@ -8,4 +8,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', `class C { /** @param {number} value */ set c(value: number) { return 12; } -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts index 9e7ef6d25fd63..a47522fe03ca1 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts @@ -16,4 +16,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {T} b */ function f(a: number, b: T) { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts index a45eb788c738c..093966231fdd2 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts @@ -14,4 +14,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {T} b */ function f(a: number, b: T) { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts index ca5dbe312e3a0..57ae42b93a335 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts @@ -24,5 +24,5 @@ function f(x: number, y: { a: string; b: Date; }, z: string, alpha, beta: any) { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts index 2a2d7f943e2e3..795ac8b5fd36d 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts @@ -26,4 +26,4 @@ verify.fileAfterApplyingRefactorAtMarker('5', function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts index a99ea8233894d..68df14c2b52a8 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts @@ -14,4 +14,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @returns {number} */ function f(x: number): number { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts index 72ddb36988e0a..7381b2f288073 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts @@ -14,4 +14,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @returns {number} */ var f = function(x: number): number { -}`, 'Annotate with types from JSDoc', 'annotate'); +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts index 6b967e8e004ac..704d3681b3d3b 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts @@ -12,4 +12,4 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param {?} x * @returns {number} */ -var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate'); +var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate'); From 0c1730a21871762c392f8d6862adfc1005743edd Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 17 Oct 2017 16:51:22 -0700 Subject: [PATCH 203/246] Fix #19257: Ensure a generated signature has a return type (#19264) * Fix #19257: Ensure a generated signature has a return type * Ensure generated properties have types * Use the same context for multiple inferences to the same property access --- src/services/codefixes/inferFromUsage.ts | 6 +++--- .../cases/fourslash/codeFixInferFromUsageCall.ts | 8 ++++++++ .../codeFixInferFromUsagePropertyAccess.ts | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/codeFixInferFromUsageCall.ts create mode 100644 tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 046eb915c1ef6..b952cc5a98db2 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -521,7 +521,7 @@ namespace ts.codefix { if (!usageContext.properties) { usageContext.properties = createUnderscoreEscapedMap(); } - const propertyUsageContext = {}; + const propertyUsageContext = usageContext.properties.get(name) || { }; inferTypeFromContext(parent, checker, propertyUsageContext); usageContext.properties.set(name, propertyUsageContext); } @@ -575,7 +575,7 @@ namespace ts.codefix { if (usageContext.properties) { usageContext.properties.forEach((context, name) => { const symbol = checker.createSymbol(SymbolFlags.Property, name); - symbol.type = getTypeFromUsageContext(context, checker); + symbol.type = getTypeFromUsageContext(context, checker) || checker.getAnyType(); members.set(name, symbol); }); } @@ -636,7 +636,7 @@ namespace ts.codefix { symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i])); parameters.push(symbol); } - const returnType = getTypeFromUsageContext(callContext.returnType, checker); + const returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType(); return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); } diff --git a/tests/cases/fourslash/codeFixInferFromUsageCall.ts b/tests/cases/fourslash/codeFixInferFromUsageCall.ts new file mode 100644 index 0000000000000..e74b6faf7d3f9 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageCall.ts @@ -0,0 +1,8 @@ +/// + +// @noImplicitAny: true +////function wat([|b |]) { +//// b(); +////} + +verify.rangeAfterCodeFix("b: () => void"); \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts new file mode 100644 index 0000000000000..c8b85ee11e88d --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsagePropertyAccess.ts @@ -0,0 +1,15 @@ +/// + +// @noImplicitAny: true +////function foo([|a, m, x |]) { +//// a.b.c; +//// +//// var numeric = 0; +//// numeric = m.n(); +//// +//// x.y.z +//// x.y.z.push(0); +//// return x.y.z +////} + +verify.rangeAfterCodeFix("a: { b: { c: any; }; }, m: { n: () => number; }, x: { y: { z: number[]; }; }", /*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, /*index*/0); \ No newline at end of file From f9df4e69e6138e2933fd3738edbf83a9e0d20ebe Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 17 Oct 2017 18:45:21 -0700 Subject: [PATCH 204/246] Respect newLine compiler option in language service output (#19279) --- Jakefile.js | 1 + src/compiler/utilities.ts | 2 +- src/harness/tsconfig.json | 3 +- src/harness/unittests/hostNewLineSupport.ts | 67 +++++++++++++++++++++ src/services/services.ts | 2 +- 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/harness/unittests/hostNewLineSupport.ts diff --git a/Jakefile.js b/Jakefile.js index 0b3659e205116..ba6943d30153d 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -154,6 +154,7 @@ var harnessSources = harnessCoreSources.concat([ "symbolWalker.ts", "languageService.ts", "publicApi.ts", + "hostNewLineSupport.ts", ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f907cce85b1f3..b08d8888d70eb 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3199,7 +3199,7 @@ namespace ts { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; - export function getNewLineCharacter(options: CompilerOptions | PrinterOptions, system?: System): string { + export function getNewLineCharacter(options: CompilerOptions | PrinterOptions, system?: { newLine: string }): string { switch (options.newLine) { case NewLineKind.CarriageReturnLineFeed: return carriageReturnLineFeed; diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index a0c141f4f1760..18baeb67c823f 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -139,6 +139,7 @@ "./unittests/telemetry.ts", "./unittests/languageService.ts", "./unittests/programMissingFiles.ts", - "./unittests/publicApi.ts" + "./unittests/publicApi.ts", + "./unittests/hostNewLineSupport.ts" ] } diff --git a/src/harness/unittests/hostNewLineSupport.ts b/src/harness/unittests/hostNewLineSupport.ts new file mode 100644 index 0000000000000..9f6b09dfb72d0 --- /dev/null +++ b/src/harness/unittests/hostNewLineSupport.ts @@ -0,0 +1,67 @@ +/// +namespace ts { + describe("hostNewLineSupport", () => { + function testLSWithFiles(settings: CompilerOptions, files: Harness.Compiler.TestFile[]) { + function snapFor(path: string): IScriptSnapshot { + if (path === "lib.d.ts") { + return { + dispose() {}, + getChangeRange() { return undefined; }, + getLength() { return 0; }, + getText(_start, _end) { + return ""; + } + }; + } + const result = forEach(files, f => f.unitName === path ? f : undefined); + if (result) { + return { + dispose() {}, + getChangeRange() { return undefined; }, + getLength() { return result.content.length; }, + getText(start, end) { + return result.content.substring(start, end); + } + }; + } + return undefined; + } + const lshost: LanguageServiceHost = { + getCompilationSettings: () => settings, + getScriptFileNames: () => map(files, f => f.unitName), + getScriptVersion: () => "1", + getScriptSnapshot: name => snapFor(name), + getDefaultLibFileName: () => "lib.d.ts", + getCurrentDirectory: () => "", + }; + return ts.createLanguageService(lshost); + } + + function verifyNewLines(content: string, options: CompilerOptions) { + const ls = testLSWithFiles(options, [{ + content, + fileOptions: {}, + unitName: "input.ts" + }]); + const result = ls.getEmitOutput("input.ts"); + assert(!result.emitSkipped, "emit was skipped"); + assert(result.outputFiles.length === 1, "a number of files other than 1 was output"); + assert(result.outputFiles[0].name === "input.js", `Expected output file name input.js, but got ${result.outputFiles[0].name}`); + assert(result.outputFiles[0].text.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); + assert(!result.outputFiles[0].text.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); + } + + function verifyBothNewLines(content: string) { + verifyNewLines(content, { newLine: NewLineKind.CarriageReturnLineFeed }); + verifyNewLines(content, { newLine: NewLineKind.LineFeed }); + } + + it("should exist and respect provided compiler options", () => { + verifyBothNewLines(` + function foo() { + return 2 + 2; + } + `); + }); + }); +} \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index a5c9c1d353a18..114692ebba2e5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1146,7 +1146,7 @@ namespace ts { getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, - getNewLine: () => getNewLineOrDefaultFromHost(host), + getNewLine: () => getNewLineCharacter(newSettings, { newLine: getNewLineOrDefaultFromHost(host) }), getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: noop, getCurrentDirectory: () => currentDirectory, From b792daab984b3e04dcf379c8c64f7c137235ff8b Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 18 Oct 2017 04:10:04 +0000 Subject: [PATCH 205/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 37 ++++++- .../diagnosticMessages.generated.json.lcl | 100 ++++++++++++++++-- 2 files changed, 127 insertions(+), 10 deletions(-) diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 43073f7cab335..c23ea7cc378a5 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -804,6 +804,9 @@ + + + @@ -1347,12 +1350,18 @@ + + + + + + @@ -1506,6 +1515,9 @@ + + + @@ -1917,8 +1929,8 @@ - - + + @@ -2040,6 +2052,9 @@ + + + @@ -3828,12 +3843,18 @@ + + + + + + @@ -4032,12 +4053,18 @@ + + + + + + @@ -7302,6 +7329,9 @@ + + + @@ -7788,6 +7818,9 @@ + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 603345e63b223..014ca9ef8f6f7 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -782,6 +782,15 @@ + + + + + + + + + @@ -1313,6 +1322,24 @@ + + + + + + + + + + + + + + + + + + @@ -1460,6 +1487,15 @@ + + + + + + + + + @@ -1867,10 +1903,13 @@ - + - + + + + @@ -1982,6 +2021,15 @@ + + + + + + + + + @@ -3758,6 +3806,24 @@ + + + + + + + + + + + + + + + + + + @@ -3950,20 +4016,20 @@ - + - + - + - + - + - + @@ -7217,6 +7283,15 @@ + + + + + + + + + @@ -7697,6 +7772,15 @@ + + + + + + + + + From d08b58c7d15aa885d79778645158246d9a60939a Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 18 Oct 2017 10:10:12 +0000 Subject: [PATCH 206/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 99 +++++++++++++++++-- 1 file changed, 90 insertions(+), 9 deletions(-) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 16310396458a1..59537bdde09d3 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,15 @@ + + + + + + + + + @@ -1329,6 +1338,24 @@ + + + + + + + + + + + + + + + + + + @@ -1476,6 +1503,15 @@ + + + + + + + + + @@ -1883,12 +1919,12 @@ - + - + - + @@ -2004,6 +2040,15 @@ + + + + + + + + + @@ -3786,6 +3831,24 @@ + + + + + + + + + + + + + + + + + + @@ -3978,20 +4041,20 @@ - + - + - + - + - + - + @@ -7254,6 +7317,15 @@ + + + + + + + + + @@ -7734,6 +7806,15 @@ + + + + + + + + + From 2ca0df8844bf630b1f8521f2100e6f2d7d5c72bd Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 18 Oct 2017 16:10:11 +0000 Subject: [PATCH 207/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 99 +++++++++++++++++-- .../diagnosticMessages.generated.json.lcl | 99 +++++++++++++++++-- .../diagnosticMessages.generated.json.lcl | 99 +++++++++++++++++-- .../diagnosticMessages.generated.json.lcl | 37 ++++++- 4 files changed, 305 insertions(+), 29 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3c83950d4f32c..014459b186046 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,15 @@ + + + + + + + + + @@ -1329,6 +1338,24 @@ + + + + + + + + + + + + + + + + + + @@ -1476,6 +1503,15 @@ + + + + + + + + + @@ -1883,12 +1919,12 @@ - + - + - + @@ -2004,6 +2040,15 @@ + + + + + + + + + @@ -3786,6 +3831,24 @@ + + + + + + + + + + + + + + + + + + @@ -3978,20 +4041,20 @@ - + - + - + - + - + - + @@ -7254,6 +7317,15 @@ + + + + + + + + + @@ -7734,6 +7806,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index de906e32915dd..7bf155734c81a 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,15 @@ + + + + + + + + + @@ -1329,6 +1338,24 @@ + + + + + + + + + + + + + + + + + + @@ -1476,6 +1503,15 @@ + + + + + + + + + @@ -1883,12 +1919,12 @@ - + - + - + @@ -2004,6 +2040,15 @@ + + + + + + + + + @@ -3786,6 +3831,24 @@ + + + + + + + + + + + + + + + + + + @@ -3978,20 +4041,20 @@ - + - + - + - + - + - + @@ -7254,6 +7317,15 @@ + + + + + + + + + @@ -7734,6 +7806,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index c25043edfa592..b2f99224643f7 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,15 @@ + + + + + + + + + @@ -1329,6 +1338,24 @@ + + + + + + + + + + + + + + + + + + @@ -1476,6 +1503,15 @@ + + + + + + + + + @@ -1883,12 +1919,12 @@ - + - + - + @@ -2004,6 +2040,15 @@ + + + + + + + + + @@ -3786,6 +3831,24 @@ + + + + + + + + + + + + + + + + + + @@ -3978,20 +4041,20 @@ - + - + - + - + - + - + @@ -7254,6 +7317,15 @@ + + + + + + + + + @@ -7734,6 +7806,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 4ae9e7d5e5697..990ca10226f34 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -785,6 +785,9 @@ + + + @@ -1322,12 +1325,18 @@ + + + + + + @@ -1481,6 +1490,9 @@ + + + @@ -1892,8 +1904,8 @@ - - + + @@ -2012,6 +2024,9 @@ + + + @@ -3794,12 +3809,18 @@ + + + + + + @@ -3998,12 +4019,18 @@ + + + + + + @@ -7259,6 +7286,9 @@ + + + @@ -7745,6 +7775,9 @@ + + + From 3220ebc182cf33465abb64666e6b8a258f830213 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 18 Oct 2017 10:23:18 -0700 Subject: [PATCH 208/246] Disambiguate same-named refactors using description (#19267) Disambiguate same-named refactors using actionName --- src/harness/fourslash.ts | 8 ++++---- tests/cases/fourslash/extract-const1.ts | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/extract-const1.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 9ac2aac764529..6724015107974 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2871,14 +2871,14 @@ Actual: ${stringify(fullActual)}`); public applyRefactor({ refactorName, actionName, actionDescription, newContent: newContentWithRenameMarker }: FourSlashInterface.ApplyRefactorOptions) { const range = this.getSelection(); const refactors = this.languageService.getApplicableRefactors(this.activeFile.fileName, range); - const refactor = refactors.find(r => r.name === refactorName); - if (!refactor) { + const refactorsWithName = refactors.filter(r => r.name === refactorName); + if (refactorsWithName.length === 0) { this.raiseError(`The expected refactor: ${refactorName} is not available at the marker location.\nAvailable refactors: ${refactors.map(r => r.name)}`); } - const action = refactor.actions.find(a => a.name === actionName); + const action = ts.firstDefined(refactorsWithName, refactor => refactor.actions.find(a => a.name === actionName)); if (!action) { - this.raiseError(`The expected action: ${action} is not included in: ${refactor.actions.map(a => a.name)}`); + this.raiseError(`The expected action: ${actionName} is not included in: ${ts.flatMap(refactorsWithName, r => r.actions.map(a => a.name))}`); } if (action.description !== actionDescription) { this.raiseError(`Expected action description to be ${JSON.stringify(actionDescription)}, got: ${JSON.stringify(action.description)}`); diff --git a/tests/cases/fourslash/extract-const1.ts b/tests/cases/fourslash/extract-const1.ts new file mode 100644 index 0000000000000..3ed9373f2bae1 --- /dev/null +++ b/tests/cases/fourslash/extract-const1.ts @@ -0,0 +1,14 @@ +/// + +////const x = /*a*/0/*b*/; + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Extract Symbol", + actionName: "constant_scope_0", + actionDescription: "Extract to constant in enclosing scope", + newContent: +`const newLocal = 0; + +const x = /*RENAME*/newLocal;` +}); From 45ba0ac3b91a1bc80cfa489b979599cef33f5392 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Mon, 16 Oct 2017 13:38:28 -0700 Subject: [PATCH 209/246] Set the scriptKind from the host configuration if present --- src/compiler/core.ts | 10 ++++++++++ src/compiler/program.ts | 6 ++++-- src/compiler/types.ts | 1 + src/server/editorServices.ts | 21 ++++++++++++++++++--- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 90dcc1ad5d4a0..d794b8177667a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2691,6 +2691,16 @@ namespace ts { return find(supportedTypescriptExtensionsForExtractExtension, e => fileExtensionIs(path, e)) || find(supportedJavascriptExtensions, e => fileExtensionIs(path, e)); } + // Retrieves any string from the final "." onwards from a base file name. + // Unlike extensionFromPath, which throws an exception on unrecognized extensions. + export function getAnyExtensionFromPath(path: string): string | undefined { + const baseFileName = getBaseFileName(path); + const extensionIndex = baseFileName.lastIndexOf("."); + if (extensionIndex >= 0) { + return baseFileName.substring(extensionIndex); + } + } + export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) { return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b8c402dbb7f86..1d325983f5fc6 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1278,8 +1278,10 @@ namespace ts { const typeChecker = getDiagnosticsProducingTypeChecker(); Debug.assert(!!sourceFile.bindDiagnostics); - // For JavaScript files, we don't want to report semantic errors unless explicitly requested. - const includeBindAndCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options); + + // By default, only type-check .ts, .tsx, and 'External' files (external files are added by plugins) + const includeBindAndCheckDiagnostics = sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX || + sourceFile.scriptKind === ScriptKind.External || isCheckJsEnabledForFile(sourceFile, options); const bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray; const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6226e4f98c723..3f9b492f90342 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3626,6 +3626,7 @@ namespace ts { export interface JsFileExtensionInfo { extension: string; isMixedContent: boolean; + scriptKind?: ScriptKind; } export interface DiagnosticMessage { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 70598313a7365..ad08cd63da6b7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -220,13 +220,28 @@ namespace ts.server { interface FilePropertyReader { getFileName(f: T): string; - getScriptKind(f: T): ScriptKind; + getScriptKind(f: T, extraFileExtensions?: JsFileExtensionInfo[]): ScriptKind; hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[]): boolean; } const fileNamePropertyReader: FilePropertyReader = { getFileName: x => x, - getScriptKind: _ => undefined, + getScriptKind: (fileName, extraFileExtensions) => { + let result: ScriptKind; + if (extraFileExtensions) { + const fileExtension = getAnyExtensionFromPath(fileName); + if (fileExtension) { + some(extraFileExtensions, info => { + if (info.extension === fileExtension) { + result = info.scriptKind; + return true; + } + return false; + }); + } + } + return result; + }, hasMixedContent: (fileName, extraFileExtensions) => some(extraFileExtensions, ext => ext.isMixedContent && fileExtensionIs(fileName, ext.extension)), }; @@ -1504,7 +1519,7 @@ namespace ts.server { scriptInfo = normalizedPath; } else { - const scriptKind = propertyReader.getScriptKind(f); + const scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions); const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions); scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, scriptKind, hasMixedContent, project.directoryStructureHost); path = scriptInfo.path; From 9da745d37ba757026f0847ef3d6942a259a87ee7 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Tue, 17 Oct 2017 16:50:32 -0700 Subject: [PATCH 210/246] Update API baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 15eca3da329f4..52132ae832f25 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2158,6 +2158,7 @@ declare namespace ts { interface JsFileExtensionInfo { extension: string; isMixedContent: boolean; + scriptKind?: ScriptKind; } interface DiagnosticMessage { key: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f3180b9d1069c..976d50942ae1b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2158,6 +2158,7 @@ declare namespace ts { interface JsFileExtensionInfo { extension: string; isMixedContent: boolean; + scriptKind?: ScriptKind; } interface DiagnosticMessage { key: string; From f37411785809e63780f826699887f890a81cdba1 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 11:32:48 -0700 Subject: [PATCH 211/246] Remove erroneous error for JSDoc object literals appears with checkJS. --- src/compiler/checker.ts | 19 +++++++++++++----- .../reference/jsdocIndexSignature.errors.txt | 18 +++++++++++++++++ .../reference/jsdocIndexSignature.symbols | 12 +++++++++++ .../reference/jsdocIndexSignature.types | 20 +++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/jsdocIndexSignature.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 219f370fd53f5..992c609929f94 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7030,13 +7030,11 @@ namespace ts { function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type { if (isIdentifier(node.typeName)) { if (node.typeName.escapedText === "Object") { - if (node.typeArguments && node.typeArguments.length === 2) { + if (isJSDocIndexSignature(node)) { const indexed = getTypeFromTypeNode(node.typeArguments[0]); const target = getTypeFromTypeNode(node.typeArguments[1]); const index = createIndexInfo(target, /*isReadonly*/ false); - if (indexed === stringType || indexed === numberType) { - return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index); - } + return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexed === stringType && index, indexed === numberType && index); } return anyType; } @@ -7066,6 +7064,14 @@ namespace ts { } } + function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { + return isTypeReferenceNode(node) && + isIdentifier(node.typeName) && + node.typeName.escapedText === "Object" && + node.typeArguments && node.typeArguments.length === 2 && + (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); + } + function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) { const type = getTypeFromTypeNode(node.type); return strictNullChecks ? getUnionType([type, nullType]) : type; @@ -19179,7 +19185,10 @@ namespace ts { // There is no resolved symbol cached if the type resolved to a builtin // via JSDoc type reference resolution (eg, Boolean became boolean), none // of which are generic when they have no associated symbol - error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); + // (additionally, JSDoc's index signature syntax, Object actually uses generic syntax without being generic) + if (!isJSDocIndexSignature(node)) { + error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); + } return; } let typeParameters = symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters; diff --git a/tests/baselines/reference/jsdocIndexSignature.errors.txt b/tests/baselines/reference/jsdocIndexSignature.errors.txt new file mode 100644 index 0000000000000..de336795b3e64 --- /dev/null +++ b/tests/baselines/reference/jsdocIndexSignature.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/jsdoc/indices.js(9,5): error TS2322: Type '1' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/jsdoc/indices.js (1 errors) ==== + /** @type {Object.} */ + var o1; + /** @type {Object.} */ + var o2; + /** @type {Object.} */ + var o3; + /** @param {Object.} o */ + function f(o) { + o.foo = 1; // error + ~~~~~ +!!! error TS2322: Type '1' is not assignable to type 'boolean'. + o.bar = false; // ok + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocIndexSignature.symbols b/tests/baselines/reference/jsdocIndexSignature.symbols index 8814fc18b6f1f..89288458f470f 100644 --- a/tests/baselines/reference/jsdocIndexSignature.symbols +++ b/tests/baselines/reference/jsdocIndexSignature.symbols @@ -11,3 +11,15 @@ var o2; var o3; >o3 : Symbol(o3, Decl(indices.js, 5, 3)) +/** @param {Object.} o */ +function f(o) { +>f : Symbol(f, Decl(indices.js, 5, 7)) +>o : Symbol(o, Decl(indices.js, 7, 11)) + + o.foo = 1; // error +>o : Symbol(o, Decl(indices.js, 7, 11)) + + o.bar = false; // ok +>o : Symbol(o, Decl(indices.js, 7, 11)) +} + diff --git a/tests/baselines/reference/jsdocIndexSignature.types b/tests/baselines/reference/jsdocIndexSignature.types index 4c1feaa2721f1..d9ac826309244 100644 --- a/tests/baselines/reference/jsdocIndexSignature.types +++ b/tests/baselines/reference/jsdocIndexSignature.types @@ -11,3 +11,23 @@ var o2; var o3; >o3 : any +/** @param {Object.} o */ +function f(o) { +>f : (o: { [x: string]: boolean; }) => void +>o : { [x: string]: boolean; } + + o.foo = 1; // error +>o.foo = 1 : 1 +>o.foo : boolean +>o : { [x: string]: boolean; } +>foo : boolean +>1 : 1 + + o.bar = false; // ok +>o.bar = false : false +>o.bar : boolean +>o : { [x: string]: boolean; } +>bar : boolean +>false : false +} + From c13506e70c57644f53baae37aee7b0d83f53eeb7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 13:04:13 -0700 Subject: [PATCH 212/246] Update annotateWithTypeFromJSDoc tests 1. Object literals are single-line now. 2. Index signatures transform to TS index signatures. 3. The refactoring is only available when it could add types. --- .../fourslash/annotateWithTypeFromJSDoc21.ts | 73 +++++++++++++++++++ .../fourslash/annotateWithTypeFromJSDoc22.ts | 14 ++++ .../fourslash/annotateWithTypeFromJSDoc3.ts | 5 +- .../fourslash/annotateWithTypeFromJSDoc4.ts | 4 +- 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts create mode 100644 tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts new file mode 100644 index 0000000000000..b54f83070c4ab --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts @@ -0,0 +1,73 @@ +/// +// @strict: true +/////** +//// * @return {number} +//// */ +////function /*1*/f(x, y) { +////} +//// +/////** +//// * @return {number} +//// */ +////function /*2*/g(x, y): number { +//// return 0; +////} +/////** +//// * @param {number} x +//// */ +////function /*3*/h(x: number, y): number { +//// return 0; +////} +//// +/////** +//// * @param {number} x +//// * @param {string} y +//// */ +////function /*4*/i(x: number, y: string) { +////} +/////** +//// * @param {number} x +//// * @return {boolean} +//// */ +////function /*5*/j(x: number, y): boolean { +//// return true; +////} + +verify.not.applicableRefactorAvailableAtMarker('2'); +verify.not.applicableRefactorAvailableAtMarker('3'); +verify.not.applicableRefactorAvailableAtMarker('4'); +verify.not.applicableRefactorAvailableAtMarker('5'); +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +`/** + * @return {number} + */ +function f(x, y): number { +} + +/** + * @return {number} + */ +function g(x, y): number { + return 0; +} +/** + * @param {number} x + */ +function h(x: number, y): number { + return 0; +} + +/** + * @param {number} x + * @param {string} y + */ +function i(x: number, y: string) { +} +/** + * @param {number} x + * @return {boolean} + */ +function j(x: number, y): boolean { + return true; +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts new file mode 100644 index 0000000000000..d00705848c642 --- /dev/null +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts @@ -0,0 +1,14 @@ +/// +// @strict: true +//// +/////** @param {Object} sb +//// * @param {Object} ns */ +////function /*1*/f(sb, ns) { +////} +verify.applicableRefactorAvailableAtMarker('1'); +verify.fileAfterApplyingRefactorAtMarker('1', +` +/** @param {Object} sb + * @param {Object} ns */ +function f(sb: { [s: string]: boolean; }, ns: { [n: number]: string; }) { +}`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts index 57ae42b93a335..9413e6046c9e4 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts @@ -20,9 +20,6 @@ verify.fileAfterApplyingRefactorAtMarker('1', * @param alpha - the other best parameter * @param {*} beta - I have no idea how this got here */ -function f(x: number, y: { - a: string; - b: Date; -}, z: string, alpha, beta: any) { +function f(x: number, y: { a: string; b: Date; }, z: string, alpha, beta: any) { }`, 'Annotate with type from JSDoc', 'annotate'); diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts index 795ac8b5fd36d..ad06bbbc699f2 100644 --- a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts +++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts @@ -23,7 +23,5 @@ verify.fileAfterApplyingRefactorAtMarker('5', * @param {number?} gamma * @param {number!} delta */ -function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { - a: string; -}, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { +function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: { a: string; }, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) { }`, 'Annotate with type from JSDoc', 'annotate'); From 2473ffcaac533a7bd6a5b5fe3a2896a6cff9a726 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 13:06:15 -0700 Subject: [PATCH 213/246] Add a better test for jsdoc index signatures. The test case shows that the errorenous error no longer appears. --- tests/cases/conformance/jsdoc/jsdocIndexSignature.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/cases/conformance/jsdoc/jsdocIndexSignature.ts b/tests/cases/conformance/jsdoc/jsdocIndexSignature.ts index fdf9e06e61eb0..29365cb91be5b 100644 --- a/tests/cases/conformance/jsdoc/jsdocIndexSignature.ts +++ b/tests/cases/conformance/jsdoc/jsdocIndexSignature.ts @@ -8,3 +8,8 @@ var o1; var o2; /** @type {Object.} */ var o3; +/** @param {Object.} o */ +function f(o) { + o.foo = 1; // error + o.bar = false; // ok +} From aa73ed822618d1819cfd37e0bfb1ca7af0933898 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 13:07:54 -0700 Subject: [PATCH 214/246] Fix bugs in jsdoc annotation refactor 1. Transform index signatures to TS index signatures. 2. Print object literals on a single line. 3. Only offer the refactor when it could add types. (There must not be a type annotation already, and there must be a JSDoc that applies.) --- .../refactors/annotateWithTypeFromJSDoc.ts | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 29da66f697441..98131d0623cb4 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -23,26 +23,30 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false); - const decl = findAncestor(node, isDeclarationWithType); - if (!decl || decl.type) { - return undefined; - } - const jsdocType = getJSDocType(decl); - const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p))); - if (isFunctionWithJSDoc || jsdocType) { + if (hasUsableJSDoc(findAncestor(node, isDeclarationWithType))) { return [{ name: annotateTypeFromJSDoc.name, description: annotateTypeFromJSDoc.description, actions: [ { - description: annotateTypeFromJSDoc.description, - name: actionName - } + description: annotateTypeFromJSDoc.description, + name: actionName + } ] }]; } } + function hasUsableJSDoc(decl: DeclarationWithType): boolean { + if (!decl) { + return false; + } + if (isFunctionLikeDeclaration(decl)) { + return decl.parameters.some(hasUsableJSDoc) || (!decl.type && !!getJSDocReturnType(decl)); + } + return !decl.type && !!getJSDocType(decl); + } + function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined { if (actionName !== action) { return Debug.fail(`actionName !== action: ${actionName} !== ${action}`); @@ -169,7 +173,9 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { case SyntaxKind.TypeReference: return transformJSDocTypeReference(node as TypeReferenceNode); default: - return visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode; + const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode; + setEmitFlags(visited, EmitFlags.SingleLine); + return visited; } } @@ -202,6 +208,9 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { let name = node.typeName; let args = node.typeArguments; if (isIdentifier(node.typeName)) { + if (isJSDocIndexSignature(node)) { + return transformJSDocIndexSignature(node); + } let text = node.typeName.text; switch (node.typeName.text) { case "String": @@ -226,4 +235,26 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { } return createTypeReferenceNode(name, args); } + + function transformJSDocIndexSignature(node: TypeReferenceNode) { + const index = createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "n" : "s", + /*questionToken*/ undefined, + createTypeReferenceNode(node.typeArguments[0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []), + /*initializer*/ undefined); + const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]); + setEmitFlags(indexSignature, EmitFlags.SingleLine); + return indexSignature; + } + + function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { + return isTypeReferenceNode(node) && + isIdentifier(node.typeName) && + node.typeName.escapedText === "Object" && + node.typeArguments && node.typeArguments.length === 2 && + (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); + } } From f82dd7b1dab62d6c3352032ad8c512bd47074bcc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 13:16:22 -0700 Subject: [PATCH 215/246] Move isJSDocIndexSignature to utilities --- src/compiler/checker.ts | 8 -------- src/compiler/utilities.ts | 8 ++++++++ src/services/refactors/annotateWithTypeFromJSDoc.ts | 8 -------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 992c609929f94..5c4db4b945195 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7064,14 +7064,6 @@ namespace ts { } } - function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { - return isTypeReferenceNode(node) && - isIdentifier(node.typeName) && - node.typeName.escapedText === "Object" && - node.typeArguments && node.typeArguments.length === 2 && - (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); - } - function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) { const type = getTypeFromTypeNode(node.type); return strictNullChecks ? getUnionType([type, nullType]) : type; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f907cce85b1f3..b1173fe81cdb3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1360,6 +1360,14 @@ namespace ts { return node && !!(node.flags & NodeFlags.JSDoc); } + export function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { + return isTypeReferenceNode(node) && + isIdentifier(node.typeName) && + node.typeName.escapedText === "Object" && + node.typeArguments && node.typeArguments.length === 2 && + (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); + } + /** * Returns true if the node is a CallExpression to the identifier 'require' with * exactly one argument (of the form 'require("name")'). diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/refactors/annotateWithTypeFromJSDoc.ts index 98131d0623cb4..d3bf59638b2be 100644 --- a/src/services/refactors/annotateWithTypeFromJSDoc.ts +++ b/src/services/refactors/annotateWithTypeFromJSDoc.ts @@ -249,12 +249,4 @@ namespace ts.refactor.annotateWithTypeFromJSDoc { setEmitFlags(indexSignature, EmitFlags.SingleLine); return indexSignature; } - - function isJSDocIndexSignature(node: TypeReferenceNode | ExpressionWithTypeArguments) { - return isTypeReferenceNode(node) && - isIdentifier(node.typeName) && - node.typeName.escapedText === "Object" && - node.typeArguments && node.typeArguments.length === 2 && - (node.typeArguments[0].kind === SyntaxKind.StringKeyword || node.typeArguments[0].kind === SyntaxKind.NumberKeyword); - } } From d3f954e0cc9ae75a3364e9518c19f0a53c7f3dae Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Oct 2017 23:02:22 -0700 Subject: [PATCH 216/246] Add failing testcase where when d.ts file is in program, the files get emitted multiple times with --out setting --- src/harness/unittests/tscWatchMode.ts | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 2ee86d4255867..fefbffa224927 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1105,6 +1105,46 @@ namespace ts.tscWatch { const outJs = "/a/out.js"; createWatchForOut(/*out*/ undefined, outJs); }); + + it("with --outFile and multiple declaration files in the program", () => { + const file1: FileOrFolder = { + path: "/a/b/output/AnotherDependency/file1.d.ts", + content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }" + }; + const file2: FileOrFolder = { + path: "/a/b/dependencies/file2.d.ts", + content: "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }" + }; + const file3: FileOrFolder = { + path: "/a/b/project/src/main.ts", + content: "namespace Main { export function fooBar() {} }" + }; + const file4: FileOrFolder = { + path: "/a/b/project/src/main2.ts", + content: "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }" + }; + const configFile: FileOrFolder = { + path: "/a/b/project/tsconfig.json", + content: JSON.stringify({ + compilerOptions: { + outFile: "../output/common.js", + target: "es5" + }, + files: [file1.path, file2.path, file3.path, file4.path] + }) + }; + const files = [file1, file2, file3, file4]; + const allfiles = files.concat(configFile); + const host = createWatchedSystem(allfiles); + const originalWriteFile = host.writeFile.bind(host); + let numberOfTimesFileWritten = 0; + host.writeFile = (p: string, content: string) => { + numberOfTimesFileWritten++; + return originalWriteFile(p, content); + }; + createWatchModeWithConfigFile(configFile.path, host); + assert.equal(numberOfTimesFileWritten, 1); + }); }); describe("tsc-watch emit for configured projects", () => { From f9c901ada7148cbaf697c4b8bdd8905ba2cc219f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 17 Oct 2017 21:18:27 -0700 Subject: [PATCH 217/246] Use get files affected by internally and hence use file paths as input --- src/compiler/builder.ts | 136 +++++++++++++++++----------------------- src/server/project.ts | 9 ++- 2 files changed, 66 insertions(+), 79 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 192f1e430278e..93b265f12ca60 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -47,11 +47,11 @@ namespace ts { /* @internal */ namespace ts { export interface Builder { - /** - * Call this to feed new program - */ + /** Called to inform builder about new program */ updateProgram(newProgram: Program): void; - getFilesAffectedBy(program: Program, path: Path): string[]; + /** Gets the files affected by the file path */ + getFilesAffectedBy(program: Program, path: Path): ReadonlyArray; + /** Emits the given file */ emitFile(program: Program, path: Path): EmitOutput; /** Emit the changed files and clear the cache of the changed files */ @@ -88,11 +88,10 @@ namespace ts { /** * Gets the files affected by the script info which has updated shape from the known one */ - getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[]; + getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray; } interface FileInfo { - fileName: string; version: string; signature: string; } @@ -109,7 +108,7 @@ namespace ts { const fileInfos = createMap(); const semanticDiagnosticsPerFile = createMap>(); /** The map has key by source file's path that has been changed */ - const changedFileNames = createMap(); + const changedFileNames = createMap(); let emitHandler: EmitHandler; return { updateProgram, @@ -142,31 +141,31 @@ namespace ts { ); } - function registerChangedFile(path: Path, fileName: string) { - changedFileNames.set(path, fileName); + function registerChangedFile(path: Path) { + changedFileNames.set(path, true); // All changed files need to re-evaluate its semantic diagnostics semanticDiagnosticsPerFile.delete(path); } function addNewFileInfo(program: Program, sourceFile: SourceFile): FileInfo { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); emitHandler.onAddSourceFile(program, sourceFile); - return { fileName: sourceFile.fileName, version: sourceFile.version, signature: undefined }; + return { version: sourceFile.version, signature: undefined }; } - function removeExistingFileInfo(existingFileInfo: FileInfo, path: Path) { - registerChangedFile(path, existingFileInfo.fileName); + function removeExistingFileInfo(_existingFileInfo: FileInfo, path: Path) { + registerChangedFile(path); emitHandler.onRemoveSourceFile(path); } function updateExistingFileInfo(program: Program, existingInfo: FileInfo, sourceFile: SourceFile) { if (existingInfo.version !== sourceFile.version) { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); existingInfo.version = sourceFile.version; emitHandler.onUpdateSourceFile(program, sourceFile); } else if (emitHandler.onUpdateSourceFileWithSameVersion(program, sourceFile)) { - registerChangedFile(sourceFile.path, sourceFile.fileName); + registerChangedFile(sourceFile.path); } } @@ -182,23 +181,23 @@ namespace ts { } } - function getFilesAffectedBy(program: Program, path: Path): string[] { + function getFilesAffectedBy(program: Program, path: Path): ReadonlyArray { ensureProgramGraph(program); - const sourceFile = program.getSourceFile(path); - const singleFileResult = sourceFile && options.shouldEmitFile(sourceFile) ? [sourceFile.fileName] : []; + const sourceFile = program.getSourceFileByPath(path); const info = fileInfos.get(path); if (!info || !updateShapeSignature(program, sourceFile, info)) { - return singleFileResult; + return sourceFile && [sourceFile] || emptyArray; } Debug.assert(!!sourceFile); - return emitHandler.getFilesAffectedByUpdatedShape(program, sourceFile, singleFileResult); + return emitHandler.getFilesAffectedByUpdatedShape(program, sourceFile); } function emitFile(program: Program, path: Path) { ensureProgramGraph(program); - if (!fileInfos.has(path)) { + const sourceFile = program.getSourceFileByPath(path); + if (!fileInfos.has(path) || options.shouldEmitFile(sourceFile)) { return { outputFiles: [], emitSkipped: true }; } @@ -207,14 +206,12 @@ namespace ts { function enumerateChangedFilesSet( program: Program, - onChangedFile: (fileName: string, path: Path) => void, - onAffectedFile: (fileName: string, sourceFile: SourceFile) => void + onAffectedFile: (sourceFile: SourceFile) => void ) { - changedFileNames.forEach((fileName, path) => { - onChangedFile(fileName, path as Path); + changedFileNames.forEach((_true, path) => { const affectedFiles = getFilesAffectedBy(program, path as Path); for (const file of affectedFiles) { - onAffectedFile(file, program.getSourceFile(file)); + onAffectedFile(file); } }); } @@ -222,27 +219,25 @@ namespace ts { function enumerateChangedFilesEmitOutput( program: Program, emitOnlyDtsFiles: boolean, - onChangedFile: (fileName: string, path: Path) => void, - onEmitOutput: (emitOutput: EmitOutputDetailed, sourceFile: SourceFile) => void + onEmitOutput: (emitOutput: EmitOutputDetailed) => void ) { const seenFiles = createMap(); - enumerateChangedFilesSet(program, onChangedFile, (fileName, sourceFile) => { - if (!seenFiles.has(fileName)) { - seenFiles.set(fileName, true); - if (sourceFile) { - // Any affected file shouldnt have the cached diagnostics - semanticDiagnosticsPerFile.delete(sourceFile.path); - - const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed; - onEmitOutput(emitOutput, sourceFile); - - // mark all the emitted source files as seen - if (emitOutput.emittedSourceFiles) { - for (const file of emitOutput.emittedSourceFiles) { - seenFiles.set(file.fileName, true); - } + enumerateChangedFilesSet(program, sourceFile => { + if (!seenFiles.has(sourceFile.path)) { + seenFiles.set(sourceFile.path, true); + // Any affected file shouldnt have the cached diagnostics + semanticDiagnosticsPerFile.delete(sourceFile.path); + + const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed; + + // mark all the emitted source files as seen + if (emitOutput.emittedSourceFiles) { + for (const file of emitOutput.emittedSourceFiles) { + seenFiles.set(file.path, true); } } + + onEmitOutput(emitOutput); } }); } @@ -250,8 +245,7 @@ namespace ts { function emitChangedFiles(program: Program): EmitOutputDetailed[] { ensureProgramGraph(program); const result: EmitOutputDetailed[] = []; - enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ false, - /*onChangedFile*/ noop, emitOutput => result.push(emitOutput)); + enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ false, emitOutput => result.push(emitOutput)); changedFileNames.clear(); return result; } @@ -260,11 +254,7 @@ namespace ts { ensureProgramGraph(program); // Ensure that changed files have cleared their respective - enumerateChangedFilesSet(program, /*onChangedFile*/ noop, (_affectedFileName, sourceFile) => { - if (sourceFile) { - semanticDiagnosticsPerFile.delete(sourceFile.path); - } - }); + enumerateChangedFilesSet(program, sourceFile => semanticDiagnosticsPerFile.delete(sourceFile.path)); let diagnostics: Diagnostic[]; for (const sourceFile of program.getSourceFiles()) { @@ -386,24 +376,20 @@ namespace ts { } /** - * Gets all the emittable files from the program. - * @param firstSourceFile This one will be emitted first. See https://github.com/Microsoft/TypeScript/issues/16888 + * Gets all files of the program excluding the default library file */ - function getAllEmittableFiles(program: Program, firstSourceFile: SourceFile): string[] { - const defaultLibraryFileName = getDefaultLibFileName(program.getCompilerOptions()); - const sourceFiles = program.getSourceFiles(); - const result: string[] = []; - add(firstSourceFile); - for (const sourceFile of sourceFiles) { + function getAllFilesExcludingDefaultLibraryFile(program: Program, firstSourceFile: SourceFile): ReadonlyArray { + let result: SourceFile[]; + for (const sourceFile of program.getSourceFiles()) { if (sourceFile !== firstSourceFile) { - add(sourceFile); + addSourceFile(sourceFile); } } - return result; + return result || emptyArray; - function add(sourceFile: SourceFile): void { - if (getBaseFileName(sourceFile.fileName) !== defaultLibraryFileName && options.shouldEmitFile(sourceFile)) { - result.push(sourceFile.fileName); + function addSourceFile(sourceFile: SourceFile) { + if (!program.isSourceFileDefaultLibrary(sourceFile)) { + (result || (result = [])).push(sourceFile); } } } @@ -417,14 +403,14 @@ namespace ts { getFilesAffectedByUpdatedShape }; - function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] { + function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray { const options = program.getCompilerOptions(); // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, // so returning the file itself is good enough. if (options && (options.out || options.outFile)) { - return singleFileResult; + return [sourceFile]; } - return getAllEmittableFiles(program, sourceFile); + return getAllFilesExcludingDefaultLibraryFile(program, sourceFile); } } @@ -481,7 +467,7 @@ namespace ts { // add files referencing the removedFilePath, as changed files too const referencedByInfo = fileInfos.get(filePath); if (referencedByInfo) { - registerChangedFile(filePath as Path, referencedByInfo.fileName); + registerChangedFile(filePath as Path); } } }); @@ -495,37 +481,33 @@ namespace ts { ); } - function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile, singleFileResult: string[]): string[] { + function getFilesAffectedByUpdatedShape(program: Program, sourceFile: SourceFile): ReadonlyArray { if (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile)) { - return getAllEmittableFiles(program, sourceFile); + return getAllFilesExcludingDefaultLibraryFile(program, sourceFile); } const compilerOptions = program.getCompilerOptions(); if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) { - return singleFileResult; + return [sourceFile]; } // Now we need to if each file in the referencedBy list has a shape change as well. // Because if so, its own referencedBy files need to be saved as well to make the // emitting result consistent with files on disk. - - const seenFileNamesMap = createMap(); - const setSeenFileName = (path: Path, sourceFile: SourceFile) => { - seenFileNamesMap.set(path, sourceFile && options.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined); - }; + const seenFileNamesMap = createMap(); // Start with the paths this file was referenced by const path = sourceFile.path; - setSeenFileName(path, sourceFile); + seenFileNamesMap.set(path, sourceFile); const queue = getReferencedByPaths(path); while (queue.length > 0) { const currentPath = queue.pop(); if (!seenFileNamesMap.has(currentPath)) { const currentSourceFile = program.getSourceFileByPath(currentPath); + seenFileNamesMap.set(currentPath, currentSourceFile); if (currentSourceFile && updateShapeSignature(program, currentSourceFile, fileInfos.get(currentPath))) { queue.push(...getReferencedByPaths(currentPath)); } - setSeenFileName(currentPath, currentSourceFile); } } diff --git a/src/server/project.ts b/src/server/project.ts index 725ce725c3881..5e6e76db986a1 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -448,18 +448,23 @@ namespace ts.server { computeHash: data => this.projectService.host.createHash(data), shouldEmitFile: sourceFile => - !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent() + !this.shouldEmitFile(sourceFile) }); } } + private shouldEmitFile(sourceFile: SourceFile) { + return !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent(); + } + getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[] { if (!this.languageServiceEnabled) { return []; } this.updateGraph(); this.ensureBuilder(); - return this.builder.getFilesAffectedBy(this.program, scriptInfo.path); + return mapDefined(this.builder.getFilesAffectedBy(this.program, scriptInfo.path), + sourceFile => this.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined); } /** From 8fbfb5ffc0dd930d95a4ed04317a70da16b43c6c Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 3 Oct 2017 15:06:56 -0700 Subject: [PATCH 218/246] Modify api to emit affected files using callback instead of generating in memory output Also marking few apis introduced during watch improvements changes that are suppose to be internal for now --- src/compiler/builder.ts | 191 ++++++++---------- src/compiler/watch.ts | 38 ++-- src/compiler/watchUtilities.ts | 4 +- src/harness/unittests/builder.ts | 16 +- src/harness/unittests/tscWatchMode.ts | 34 +++- src/server/project.ts | 26 +-- src/services/services.ts | 4 +- src/services/types.ts | 1 - .../reference/api/tsserverlibrary.d.ts | 26 +-- tests/baselines/reference/api/typescript.d.ts | 7 - 10 files changed, 141 insertions(+), 206 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 93b265f12ca60..cd678b6f361fd 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -6,56 +6,36 @@ namespace ts { emitSkipped: boolean; } - export interface EmitOutputDetailed extends EmitOutput { - diagnostics: Diagnostic[]; - sourceMaps: SourceMapData[]; - emittedSourceFiles: SourceFile[]; - } - export interface OutputFile { name: string; writeByteOrderMark: boolean; text: string; } +} - export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean, - cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitOutput | EmitOutputDetailed { +/* @internal */ +namespace ts { + export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, + cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitOutput { const outputFiles: OutputFile[] = []; - let emittedSourceFiles: SourceFile[]; const emitResult = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); - if (!isDetailed) { return { outputFiles, emitSkipped: emitResult.emitSkipped }; - } - - return { - outputFiles, - emitSkipped: emitResult.emitSkipped, - diagnostics: emitResult.diagnostics, - sourceMaps: emitResult.sourceMaps, - emittedSourceFiles - }; - function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, _onError: (message: string) => void, sourceFiles: SourceFile[]) { + function writeFile(fileName: string, text: string, writeByteOrderMark: boolean) { outputFiles.push({ name: fileName, writeByteOrderMark, text }); - if (isDetailed) { - emittedSourceFiles = addRange(emittedSourceFiles, sourceFiles); - } } } -} -/* @internal */ -namespace ts { export interface Builder { /** Called to inform builder about new program */ updateProgram(newProgram: Program): void; + /** Gets the files affected by the file path */ getFilesAffectedBy(program: Program, path: Path): ReadonlyArray; - /** Emits the given file */ - emitFile(program: Program, path: Path): EmitOutput; /** Emit the changed files and clear the cache of the changed files */ - emitChangedFiles(program: Program): EmitOutputDetailed[]; + emitChangedFiles(program: Program, writeFileCallback: WriteFileCallback): ReadonlyArray; + /** When called gets the semantic diagnostics for the program. It also caches the diagnostics and manage them */ getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[]; @@ -98,9 +78,7 @@ namespace ts { export interface BuilderOptions { getCanonicalFileName: (fileName: string) => string; - getEmitOutput: (program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) => EmitOutput | EmitOutputDetailed; computeHash: (data: string) => string; - shouldEmitFile: (sourceFile: SourceFile) => boolean; } export function createBuilder(options: BuilderOptions): Builder { @@ -108,12 +86,13 @@ namespace ts { const fileInfos = createMap(); const semanticDiagnosticsPerFile = createMap>(); /** The map has key by source file's path that has been changed */ - const changedFileNames = createMap(); + const changedFilesSet = createMap(); + const hasShapeChanged = createMap(); + let allFilesExcludingDefaultLibraryFile: ReadonlyArray | undefined; let emitHandler: EmitHandler; return { updateProgram, getFilesAffectedBy, - emitFile, emitChangedFiles, getSemanticDiagnostics, clear @@ -127,6 +106,8 @@ namespace ts { fileInfos.clear(); semanticDiagnosticsPerFile.clear(); } + hasShapeChanged.clear(); + allFilesExcludingDefaultLibraryFile = undefined; mutateMap( fileInfos, arrayToMap(program.getSourceFiles(), sourceFile => sourceFile.path), @@ -142,7 +123,7 @@ namespace ts { } function registerChangedFile(path: Path) { - changedFileNames.set(path, true); + changedFilesSet.set(path, true); // All changed files need to re-evaluate its semantic diagnostics semanticDiagnosticsPerFile.delete(path); } @@ -185,101 +166,79 @@ namespace ts { ensureProgramGraph(program); const sourceFile = program.getSourceFileByPath(path); - const info = fileInfos.get(path); - if (!info || !updateShapeSignature(program, sourceFile, info)) { - return sourceFile && [sourceFile] || emptyArray; + if (!sourceFile) { + return emptyArray; } - Debug.assert(!!sourceFile); + if (!updateShapeSignature(program, sourceFile)) { + return [sourceFile]; + } return emitHandler.getFilesAffectedByUpdatedShape(program, sourceFile); } - function emitFile(program: Program, path: Path) { + function emitChangedFiles(program: Program, writeFileCallback: WriteFileCallback): ReadonlyArray { ensureProgramGraph(program); - const sourceFile = program.getSourceFileByPath(path); - if (!fileInfos.has(path) || options.shouldEmitFile(sourceFile)) { - return { outputFiles: [], emitSkipped: true }; - } - - return options.getEmitOutput(program, program.getSourceFileByPath(path), /*emitOnlyDtsFiles*/ false, /*isDetailed*/ false); - } - - function enumerateChangedFilesSet( - program: Program, - onAffectedFile: (sourceFile: SourceFile) => void - ) { - changedFileNames.forEach((_true, path) => { - const affectedFiles = getFilesAffectedBy(program, path as Path); - for (const file of affectedFiles) { - onAffectedFile(file); - } - }); - } - - function enumerateChangedFilesEmitOutput( - program: Program, - emitOnlyDtsFiles: boolean, - onEmitOutput: (emitOutput: EmitOutputDetailed) => void - ) { + const compilerOptions = program.getCompilerOptions(); + let result: EmitResult[] | undefined; const seenFiles = createMap(); - enumerateChangedFilesSet(program, sourceFile => { - if (!seenFiles.has(sourceFile.path)) { - seenFiles.set(sourceFile.path, true); - // Any affected file shouldnt have the cached diagnostics - semanticDiagnosticsPerFile.delete(sourceFile.path); - - const emitOutput = options.getEmitOutput(program, sourceFile, emitOnlyDtsFiles, /*isDetailed*/ true) as EmitOutputDetailed; - - // mark all the emitted source files as seen - if (emitOutput.emittedSourceFiles) { - for (const file of emitOutput.emittedSourceFiles) { - seenFiles.set(file.path, true); + changedFilesSet.forEach((_true, path) => { + const affectedFiles = getFilesAffectedBy(program, path as Path); + affectedFiles.forEach(affectedFile => { + // Affected files shouldnt have cached diagnostics + semanticDiagnosticsPerFile.delete(affectedFile.path); + + if (!seenFiles.has(affectedFile.path)) { + seenFiles.set(affectedFile.path, true); + + // With --out or --outFile all outputs go into single file, do it only once + if (compilerOptions.outFile || compilerOptions.out) { + if (!result) { + result = [program.emit(affectedFile, writeFileCallback)]; + } + } + else { + // Emit the affected file + (result || (result = [])).push(program.emit(affectedFile, writeFileCallback)); } } - - onEmitOutput(emitOutput); - } + }); }); - } - - function emitChangedFiles(program: Program): EmitOutputDetailed[] { - ensureProgramGraph(program); - const result: EmitOutputDetailed[] = []; - enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ false, emitOutput => result.push(emitOutput)); - changedFileNames.clear(); - return result; + changedFilesSet.clear(); + return result || emptyArray; } function getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[] { ensureProgramGraph(program); - - // Ensure that changed files have cleared their respective - enumerateChangedFilesSet(program, sourceFile => semanticDiagnosticsPerFile.delete(sourceFile.path)); + Debug.assert(changedFilesSet.size === 0); let diagnostics: Diagnostic[]; for (const sourceFile of program.getSourceFiles()) { - const path = sourceFile.path; - const cachedDiagnostics = semanticDiagnosticsPerFile.get(path); - // Report the semantic diagnostics from the cache if we already have those diagnostics present - if (cachedDiagnostics) { - diagnostics = addRange(diagnostics, cachedDiagnostics); - } - else { - // Diagnostics werent cached, get them from program, and cache the result - const cachedDiagnostics = program.getSemanticDiagnostics(sourceFile, cancellationToken); - semanticDiagnosticsPerFile.set(path, cachedDiagnostics); - diagnostics = addRange(diagnostics, cachedDiagnostics); - } + diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(program, sourceFile, cancellationToken)); } return diagnostics || emptyArray; } + function getSemanticDiagnosticsOfFile(program: Program, sourceFile: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray { + const path = sourceFile.path; + const cachedDiagnostics = semanticDiagnosticsPerFile.get(path); + // Report the semantic diagnostics from the cache if we already have those diagnostics present + if (cachedDiagnostics) { + cachedDiagnostics; + } + + // Diagnostics werent cached, get them from program, and cache the result + const diagnostics = program.getSemanticDiagnostics(sourceFile, cancellationToken); + semanticDiagnosticsPerFile.set(path, diagnostics); + return diagnostics; + } + function clear() { isModuleEmit = undefined; emitHandler = undefined; fileInfos.clear(); semanticDiagnosticsPerFile.clear(); - changedFileNames.clear(); + changedFilesSet.clear(); + hasShapeChanged.clear(); } /** @@ -300,7 +259,18 @@ namespace ts { /** * @return {boolean} indicates if the shape signature has changed since last update. */ - function updateShapeSignature(program: Program, sourceFile: SourceFile, info: FileInfo) { + function updateShapeSignature(program: Program, sourceFile: SourceFile) { + Debug.assert(!!sourceFile); + + // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate + if (hasShapeChanged.has(sourceFile.path)) { + return false; + } + + hasShapeChanged.set(sourceFile.path, true); + const info = fileInfos.get(sourceFile.path); + Debug.assert(!!info); + const prevSignature = info.signature; let latestSignature: string; if (sourceFile.isDeclarationFile) { @@ -308,7 +278,7 @@ namespace ts { info.signature = latestSignature; } else { - const emitOutput = options.getEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true, /*isDetailed*/ false); + const emitOutput = getFileEmitOutput(program, sourceFile, /*emitOnlyDtsFiles*/ true); if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) { latestSignature = options.computeHash(emitOutput.outputFiles[0].text); info.signature = latestSignature; @@ -379,13 +349,20 @@ namespace ts { * Gets all files of the program excluding the default library file */ function getAllFilesExcludingDefaultLibraryFile(program: Program, firstSourceFile: SourceFile): ReadonlyArray { + // Use cached result + if (allFilesExcludingDefaultLibraryFile) { + return allFilesExcludingDefaultLibraryFile; + } + let result: SourceFile[]; + addSourceFile(firstSourceFile); for (const sourceFile of program.getSourceFiles()) { if (sourceFile !== firstSourceFile) { addSourceFile(sourceFile); } } - return result || emptyArray; + allFilesExcludingDefaultLibraryFile = result || emptyArray; + return allFilesExcludingDefaultLibraryFile; function addSourceFile(sourceFile: SourceFile) { if (!program.isSourceFileDefaultLibrary(sourceFile)) { @@ -505,7 +482,7 @@ namespace ts { if (!seenFileNamesMap.has(currentPath)) { const currentSourceFile = program.getSourceFileByPath(currentPath); seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(program, currentSourceFile, fileInfos.get(currentPath))) { + if (currentSourceFile && updateShapeSignature(program, currentSourceFile)) { queue.push(...getReferencedByPaths(currentPath)); } } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 6f61469197b21..53692fe1e0488 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -144,13 +144,14 @@ namespace ts { function compileWatchedProgram(host: DirectoryStructureHost, program: Program, builder: Builder) { // First get and report any syntactic errors. - let diagnostics = program.getSyntacticDiagnostics().slice(); + const diagnostics = program.getSyntacticDiagnostics().slice(); let reportSemanticDiagnostics = false; // If we didn't have any syntactic errors, then also try getting the global and // semantic errors. if (diagnostics.length === 0) { - diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); + addRange(diagnostics, program.getOptionsDiagnostics()); + addRange(diagnostics, program.getGlobalDiagnostics()); if (diagnostics.length === 0) { reportSemanticDiagnostics = true; @@ -162,7 +163,7 @@ namespace ts { let sourceMaps: SourceMapData[]; let emitSkipped: boolean; - const result = builder.emitChangedFiles(program); + const result = builder.emitChangedFiles(program, writeFile); if (result.length === 0) { emitSkipped = true; } @@ -171,14 +172,13 @@ namespace ts { if (emitOutput.emitSkipped) { emitSkipped = true; } - diagnostics = concatenate(diagnostics, emitOutput.diagnostics); + addRange(diagnostics, emitOutput.diagnostics); sourceMaps = concatenate(sourceMaps, emitOutput.sourceMaps); - writeOutputFiles(emitOutput.outputFiles); } } if (reportSemanticDiagnostics) { - diagnostics = diagnostics.concat(builder.getSemanticDiagnostics(program)); + addRange(diagnostics, builder.getSemanticDiagnostics(program)); } return handleEmitOutputAndReportErrors(host, program, emittedFiles, emitSkipped, diagnostics, reportDiagnostic); @@ -191,31 +191,23 @@ namespace ts { } } - function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { + function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) { try { performance.mark("beforeIOWrite"); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - host.writeFile(fileName, data, writeByteOrderMark); + host.writeFile(fileName, text, writeByteOrderMark); performance.mark("afterIOWrite"); performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); + + if (emittedFiles) { + emittedFiles.push(fileName); + } } catch (e) { - return createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, e); - } - } - - function writeOutputFiles(outputFiles: OutputFile[]) { - if (outputFiles) { - for (const outputFile of outputFiles) { - const error = writeFile(outputFile.name, outputFile.text, outputFile.writeByteOrderMark); - if (error) { - diagnostics.push(error); - } - if (emittedFiles) { - emittedFiles.push(outputFile.name); - } + if (onError) { + onError(e.message); } } } @@ -308,7 +300,7 @@ namespace ts { getCurrentDirectory() ); // There is no extra check needed since we can just rely on the program to decide emit - const builder = createBuilder({ getCanonicalFileName, getEmitOutput: getFileEmitOutput, computeHash, shouldEmitFile: () => true }); + const builder = createBuilder({ getCanonicalFileName, computeHash }); synchronizeProgram(); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 26bf689401a8c..f39024d5a7cfd 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -1,5 +1,6 @@ /// +/* @internal */ namespace ts { /** * Updates the existing missing file watches with the new set of missing files after new program is created @@ -72,10 +73,7 @@ namespace ts { existingWatchedForWildcards.set(directory, createWildcardDirectoryWatcher(directory, flags)); } } -} -/* @internal */ -namespace ts { export function addFileWatcher(host: System, file: string, cb: FileWatcherCallback): FileWatcher { return host.watchFile(file, cb); } diff --git a/src/harness/unittests/builder.ts b/src/harness/unittests/builder.ts index edd471e9ebe9e..bfdeb1a40678a 100644 --- a/src/harness/unittests/builder.ts +++ b/src/harness/unittests/builder.ts @@ -46,15 +46,14 @@ namespace ts { function makeAssertChanges(getProgram: () => Program): (fileNames: ReadonlyArray) => void { const builder = createBuilder({ getCanonicalFileName: identity, - getEmitOutput: getFileEmitOutput, - computeHash: identity, - shouldEmitFile: returnTrue, + computeHash: identity }); return fileNames => { const program = getProgram(); builder.updateProgram(program); - const changedFiles = builder.emitChangedFiles(program); - assert.deepEqual(changedFileNames(changedFiles), fileNames); + const outputFileNames: string[] = []; + builder.emitChangedFiles(program, fileName => outputFileNames.push(fileName)); + assert.deepEqual(outputFileNames, fileNames); }; } @@ -63,11 +62,4 @@ namespace ts { updateProgramText(files, fileName, fileContent); }); } - - function changedFileNames(changedFiles: ReadonlyArray): string[] { - return changedFiles.map(f => { - assert.lengthOf(f.outputFiles, 1); - return f.outputFiles[0].name; - }); - } } diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index fefbffa224927..308021f0b0a84 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1106,7 +1106,7 @@ namespace ts.tscWatch { createWatchForOut(/*out*/ undefined, outJs); }); - it("with --outFile and multiple declaration files in the program", () => { + function verifyFilesEmittedOnce(useOutFile: boolean) { const file1: FileOrFolder = { path: "/a/b/output/AnotherDependency/file1.d.ts", content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }" @@ -1126,10 +1126,9 @@ namespace ts.tscWatch { const configFile: FileOrFolder = { path: "/a/b/project/tsconfig.json", content: JSON.stringify({ - compilerOptions: { - outFile: "../output/common.js", - target: "es5" - }, + compilerOptions: useOutFile ? + { outFile: "../output/common.js", target: "es5" } : + { outDir: "../output", target: "es5" }, files: [file1.path, file2.path, file3.path, file4.path] }) }; @@ -1137,13 +1136,32 @@ namespace ts.tscWatch { const allfiles = files.concat(configFile); const host = createWatchedSystem(allfiles); const originalWriteFile = host.writeFile.bind(host); - let numberOfTimesFileWritten = 0; + const mapOfFilesWritten = createMap(); host.writeFile = (p: string, content: string) => { - numberOfTimesFileWritten++; + const count = mapOfFilesWritten.get(p); + mapOfFilesWritten.set(p, count ? count + 1 : 1); return originalWriteFile(p, content); }; createWatchModeWithConfigFile(configFile.path, host); - assert.equal(numberOfTimesFileWritten, 1); + if (useOutFile) { + // Only out file + assert.equal(mapOfFilesWritten.size, 1); + } + else { + // main.js and main2.js + assert.equal(mapOfFilesWritten.size, 2); + } + mapOfFilesWritten.forEach((value, key) => { + assert.equal(value, 1, "Key: " + key); + }); + } + + it("with --outFile and multiple declaration files in the program", () => { + verifyFilesEmittedOnce(/*useOutFile*/ true); + }); + + it("without --outFile and multiple declaration files in the program", () => { + verifyFilesEmittedOnce(/*useOutFile*/ false); }); }); diff --git a/src/server/project.ts b/src/server/project.ts index 5e6e76db986a1..3cadfd6822499 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -443,18 +443,13 @@ namespace ts.server { if (!this.builder) { this.builder = createBuilder({ getCanonicalFileName: this.projectService.toCanonicalFileName, - getEmitOutput: (_program, sourceFile, emitOnlyDts, isDetailed) => - this.getFileEmitOutput(sourceFile, emitOnlyDts, isDetailed), - computeHash: data => - this.projectService.host.createHash(data), - shouldEmitFile: sourceFile => - !this.shouldEmitFile(sourceFile) + computeHash: data => this.projectService.host.createHash(data) }); } } - private shouldEmitFile(sourceFile: SourceFile) { - return !this.projectService.getScriptInfoForPath(sourceFile.path).isDynamicOrHasMixedContent(); + private shouldEmitFile(scriptInfo: ScriptInfo) { + return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent(); } getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[] { @@ -464,15 +459,17 @@ namespace ts.server { this.updateGraph(); this.ensureBuilder(); return mapDefined(this.builder.getFilesAffectedBy(this.program, scriptInfo.path), - sourceFile => this.shouldEmitFile(sourceFile) ? sourceFile.fileName : undefined); + sourceFile => this.shouldEmitFile(this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined); } /** * Returns true if emit was conducted */ emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): boolean { - this.ensureBuilder(); - const { emitSkipped, outputFiles } = this.builder.emitFile(this.program, scriptInfo.path); + if (!this.languageServiceEnabled || !this.shouldEmitFile(scriptInfo)) { + return false; + } + const { emitSkipped, outputFiles } = this.getLanguageService(/*ensureSynchronized*/ false).getEmitOutput(scriptInfo.fileName); if (!emitSkipped) { for (const outputFile of outputFiles) { const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, this.currentDirectory); @@ -598,13 +595,6 @@ namespace ts.server { }); } - private getFileEmitOutput(sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean) { - if (!this.languageServiceEnabled) { - return undefined; - } - return this.getLanguageService(/*ensureSynchronized*/ false).getEmitOutput(sourceFile.fileName, emitOnlyDtsFiles, isDetailed); - } - getExcludedFiles(): ReadonlyArray { return emptyArray; } diff --git a/src/services/services.ts b/src/services/services.ts index 114692ebba2e5..2923acf404cef 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1511,12 +1511,12 @@ namespace ts { return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, isDetailed?: boolean) { + function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean) { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); const customTransformers = host.getCustomTransformers && host.getCustomTransformers(); - return getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, isDetailed, cancellationToken, customTransformers); + return getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers); } // Signature help diff --git a/src/services/types.ts b/src/services/types.ts index 7ec559be92283..f9d725c2fa3e3 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -287,7 +287,6 @@ namespace ts { getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, isDetailed?: boolean): EmitOutput | EmitOutputDetailed; getProgram(): Program; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 52132ae832f25..5f3d90e5ad0e5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3731,17 +3731,11 @@ declare namespace ts { outputFiles: OutputFile[]; emitSkipped: boolean; } - interface EmitOutputDetailed extends EmitOutput { - diagnostics: Diagnostic[]; - sourceMaps: SourceMapData[]; - emittedSourceFiles: SourceFile[]; - } interface OutputFile { name: string; writeByteOrderMark: boolean; text: string; } - function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitOutput | EmitOutputDetailed; } declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string; @@ -3953,7 +3947,6 @@ declare namespace ts { getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, isDetailed?: boolean): EmitOutput | EmitOutputDetailed; getProgram(): Program; dispose(): void; } @@ -7043,23 +7036,6 @@ declare namespace ts.server { isJavaScript(): boolean; } } -declare namespace ts { - /** - * Updates the existing missing file watches with the new set of missing files after new program is created - */ - function updateMissingFilePathsWatch(program: Program, missingFileWatches: Map, createMissingFileWatch: (missingFilePath: Path) => FileWatcher): void; - interface WildcardDirectoryWatcher { - watcher: FileWatcher; - flags: WatchDirectoryFlags; - } - /** - * Updates the existing wild card directory watches with the new set of wild card directories from the config file - * after new program is created because the config file was reloaded or program was created first time from the config file - * Note that there is no need to call this function when the program is updated with additional files without reloading config files, - * as wildcard directories wont change unless reloading config file - */ - function updateWatchingWildcardDirectories(existingWatchedForWildcards: Map, wildcardDirectories: Map, watchDirectory: (directory: string, flags: WatchDirectoryFlags) => FileWatcher): void; -} declare namespace ts.server { interface InstallPackageOptionsWithProjectRootPath extends InstallPackageOptions { projectRootPath: Path; @@ -7204,6 +7180,7 @@ declare namespace ts.server { getAllProjectErrors(): ReadonlyArray; getLanguageService(ensureSynchronized?: boolean): LanguageService; private ensureBuilder(); + private shouldEmitFile(scriptInfo); getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[]; /** * Returns true if emit was conducted @@ -7222,7 +7199,6 @@ declare namespace ts.server { getRootFiles(): NormalizedPath[]; getRootScriptInfos(): ScriptInfo[]; getScriptInfos(): ScriptInfo[]; - private getFileEmitOutput(sourceFile, emitOnlyDtsFiles, isDetailed); getExcludedFiles(): ReadonlyArray; getFileNames(excludeFilesFromExternalLibraries?: boolean, excludeConfigFiles?: boolean): NormalizedPath[]; hasConfigFile(configFilePath: NormalizedPath): boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 976d50942ae1b..d14def7d79156 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3678,17 +3678,11 @@ declare namespace ts { outputFiles: OutputFile[]; emitSkipped: boolean; } - interface EmitOutputDetailed extends EmitOutput { - diagnostics: Diagnostic[]; - sourceMaps: SourceMapData[]; - emittedSourceFiles: SourceFile[]; - } interface OutputFile { name: string; writeByteOrderMark: boolean; text: string; } - function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, isDetailed: boolean, cancellationToken?: CancellationToken, customTransformers?: CustomTransformers): EmitOutput | EmitOutputDetailed; } declare namespace ts { function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string; @@ -3953,7 +3947,6 @@ declare namespace ts { getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, isDetailed?: boolean): EmitOutput | EmitOutputDetailed; getProgram(): Program; dispose(): void; } From 835d7cb910f3acd44b72b87b6606e5e08b386dce Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Oct 2017 12:50:36 -0700 Subject: [PATCH 219/246] Simplify emit changed files further Also use source file version as the signature of declaration file instead of computing it from text --- src/compiler/builder.ts | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index cd678b6f361fd..1b110704e7540 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -135,7 +135,10 @@ namespace ts { } function removeExistingFileInfo(_existingFileInfo: FileInfo, path: Path) { - registerChangedFile(path); + // Since we dont need to track removed file as changed file + // We can just remove its diagnostics + changedFilesSet.delete(path); + semanticDiagnosticsPerFile.delete(path); emitHandler.onRemoveSourceFile(path); } @@ -179,9 +182,22 @@ namespace ts { function emitChangedFiles(program: Program, writeFileCallback: WriteFileCallback): ReadonlyArray { ensureProgramGraph(program); const compilerOptions = program.getCompilerOptions(); - let result: EmitResult[] | undefined; + + if (!changedFilesSet.size) { + return emptyArray; + } + + // With --out or --outFile all outputs go into single file, do it only once + if (compilerOptions.outFile || compilerOptions.out) { + semanticDiagnosticsPerFile.clear(); + changedFilesSet.clear(); + return [program.emit(/*targetSourceFile*/ undefined, writeFileCallback)]; + } + const seenFiles = createMap(); + let result: EmitResult[] | undefined; changedFilesSet.forEach((_true, path) => { + // Get the affected Files by this program const affectedFiles = getFilesAffectedBy(program, path as Path); affectedFiles.forEach(affectedFile => { // Affected files shouldnt have cached diagnostics @@ -190,16 +206,8 @@ namespace ts { if (!seenFiles.has(affectedFile.path)) { seenFiles.set(affectedFile.path, true); - // With --out or --outFile all outputs go into single file, do it only once - if (compilerOptions.outFile || compilerOptions.out) { - if (!result) { - result = [program.emit(affectedFile, writeFileCallback)]; - } - } - else { - // Emit the affected file - (result || (result = [])).push(program.emit(affectedFile, writeFileCallback)); - } + // Emit the affected file + (result || (result = [])).push(program.emit(affectedFile, writeFileCallback)); } }); }); @@ -274,7 +282,7 @@ namespace ts { const prevSignature = info.signature; let latestSignature: string; if (sourceFile.isDeclarationFile) { - latestSignature = options.computeHash(sourceFile.text); + latestSignature = sourceFile.version; info.signature = latestSignature; } else { From 7e780c0a1a4cc881dac93f0eddead090aef719d7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Oct 2017 13:43:20 -0700 Subject: [PATCH 220/246] Do not cache the semantic diagnostics when compiler options has --out since we would anyways get all fresh diagnostics --- src/compiler/builder.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 1b110704e7540..49a5bfc8d974a 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -37,7 +37,7 @@ namespace ts { emitChangedFiles(program: Program, writeFileCallback: WriteFileCallback): ReadonlyArray; /** When called gets the semantic diagnostics for the program. It also caches the diagnostics and manage them */ - getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[]; + getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): ReadonlyArray; /** Called to reset the status of the builder */ clear(): void; @@ -189,7 +189,7 @@ namespace ts { // With --out or --outFile all outputs go into single file, do it only once if (compilerOptions.outFile || compilerOptions.out) { - semanticDiagnosticsPerFile.clear(); + Debug.assert(semanticDiagnosticsPerFile.size === 0); changedFilesSet.clear(); return [program.emit(/*targetSourceFile*/ undefined, writeFileCallback)]; } @@ -215,10 +215,17 @@ namespace ts { return result || emptyArray; } - function getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[] { + function getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): ReadonlyArray { ensureProgramGraph(program); Debug.assert(changedFilesSet.size === 0); + const compilerOptions = program.getCompilerOptions(); + if (compilerOptions.outFile || compilerOptions.out) { + Debug.assert(semanticDiagnosticsPerFile.size === 0); + // We dont need to cache the diagnostics just return them from program + return program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken); + } + let diagnostics: Diagnostic[]; for (const sourceFile of program.getSourceFiles()) { diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(program, sourceFile, cancellationToken)); From 75a687b524f75c2ab5bec44271408c14f86386e9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 18 Oct 2017 14:57:18 -0700 Subject: [PATCH 221/246] make getCurrentDirectory required (#19303) --- src/harness/unittests/extractTestHelpers.ts | 1 + src/services/types.ts | 1 + tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 4 files changed, 4 insertions(+) diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index 49c2c1d327704..fb2a94c361a0b 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -103,6 +103,7 @@ namespace ts { getScriptVersion: notImplemented, getScriptSnapshot: notImplemented, getDefaultLibFileName: notImplemented, + getCurrentDirectory: notImplemented, }; export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage) { diff --git a/src/services/types.ts b/src/services/types.ts index 7ec559be92283..31c05a45dc0d8 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -163,6 +163,7 @@ namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; + getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ab39d0a6d6ccc..72c3b665617ff 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3884,6 +3884,7 @@ declare namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; + getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 976d50942ae1b..374a9f4120289 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3884,6 +3884,7 @@ declare namespace ts { getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; + getCurrentDirectory(): string; getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; From 7d23ed152b6d00224b06129c6985edf44fdc458d Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 18 Oct 2017 22:10:31 +0000 Subject: [PATCH 222/246] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 35 +++++++++++++++++- .../diagnosticMessages.generated.json.lcl | 37 ++++++++++++++++++- .../diagnosticMessages.generated.json.lcl | 37 ++++++++++++++++++- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index d27b3a500b880..7f0200d6662dd 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -804,6 +804,9 @@ + + + @@ -1347,12 +1350,18 @@ + + + + + + @@ -1506,6 +1515,9 @@ + + + @@ -1917,7 +1929,7 @@ - + @@ -2040,6 +2052,9 @@ + + + @@ -3828,12 +3843,18 @@ + + + + + + @@ -4032,12 +4053,18 @@ + + + + + + @@ -7302,6 +7329,9 @@ + + + @@ -7788,6 +7818,9 @@ + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 727bf964abf21..51208134ad73e 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -795,6 +795,9 @@ + + + @@ -1338,12 +1341,18 @@ + + + + + + @@ -1497,6 +1506,9 @@ + + + @@ -1908,8 +1920,8 @@ - - + + @@ -2031,6 +2043,9 @@ + + + @@ -3819,12 +3834,18 @@ + + + + + + @@ -4023,12 +4044,18 @@ + + + + + + @@ -7293,6 +7320,9 @@ + + + @@ -7779,6 +7809,9 @@ + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index b0e6c4b3495f0..7c2b517078cf7 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -794,6 +794,9 @@ + + + @@ -1337,12 +1340,18 @@ + + + + + + @@ -1496,6 +1505,9 @@ + + + @@ -1907,8 +1919,8 @@ - - + + @@ -2030,6 +2042,9 @@ + + + @@ -3818,12 +3833,18 @@ + + + + + + @@ -4022,12 +4043,18 @@ + + + + + + @@ -7292,6 +7319,9 @@ + + + @@ -7778,6 +7808,9 @@ + + + From 9bea0dbdc2ed6ab6ccd8ca005ca422eb28f58924 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 18 Oct 2017 15:28:20 -0700 Subject: [PATCH 223/246] Actually use cached semantic diagnostics --- src/compiler/builder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 49a5bfc8d974a..635855083c08d 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -238,7 +238,7 @@ namespace ts { const cachedDiagnostics = semanticDiagnosticsPerFile.get(path); // Report the semantic diagnostics from the cache if we already have those diagnostics present if (cachedDiagnostics) { - cachedDiagnostics; + return cachedDiagnostics; } // Diagnostics werent cached, get them from program, and cache the result From 93c2b10f6861b52a96444375a5025d9c81eb8209 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 15:29:11 -0700 Subject: [PATCH 224/246] Fix tsc-instrumented 1. Make recursiveCreateDirectory correctly handle relative paths. 2. Remove dependency on Harness 3. Correctly increment iocapture0, iocapture1, ... iocaptureN. 4. Stop double-nesting baseline files. --- src/compiler/sys.ts | 3 +-- src/harness/loggedIO.ts | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index fa3ec22f586cd..c68292078cdcc 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -570,10 +570,9 @@ namespace ts { realpath }; } - function recursiveCreateDirectory(directoryPath: string, sys: System) { const basePath = getDirectoryPath(directoryPath); - const shouldCreateParent = directoryPath !== basePath && !sys.directoryExists(basePath); + const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath); if (shouldCreateParent) { recursiveCreateDirectory(basePath, sys); } diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 3123024f41947..ecdcc1a740d98 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -157,11 +157,20 @@ namespace Playback { return log; } + const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux + function sanitizeTestFilePath(name: string) { + const path = ts.toPath(ts.normalizeSlashes(name.replace(/[\^<>:"|?*%]/g, "_")).replace(/\.\.\//g, "__dotdot/"), "", canonicalizeForHarness); + if (ts.startsWith(path, "/")) { + return path.substring(1); + } + return path; + } + export function oldStyleLogIntoNewStyleLog(log: IOLog, writeFile: typeof Harness.IO.writeFile, baseTestName: string) { if (log.filesAppended) { for (const file of log.filesAppended) { if (file.contents !== undefined) { - file.contentsPath = ts.combinePaths("appended", Harness.Compiler.sanitizeTestFilePath(file.path)); + file.contentsPath = ts.combinePaths("appended", sanitizeTestFilePath(file.path)); writeFile(ts.combinePaths(baseTestName, file.contentsPath), file.contents); delete file.contents; } @@ -170,7 +179,7 @@ namespace Playback { if (log.filesWritten) { for (const file of log.filesWritten) { if (file.contents !== undefined) { - file.contentsPath = ts.combinePaths("written", Harness.Compiler.sanitizeTestFilePath(file.path)); + file.contentsPath = ts.combinePaths("written", sanitizeTestFilePath(file.path)); writeFile(ts.combinePaths(baseTestName, file.contentsPath), file.contents); delete file.contents; } @@ -180,7 +189,7 @@ namespace Playback { for (const file of log.filesRead) { const { contents } = file.result; if (contents !== undefined) { - file.result.contentsPath = ts.combinePaths("read", Harness.Compiler.sanitizeTestFilePath(file.path)); + file.result.contentsPath = ts.combinePaths("read", sanitizeTestFilePath(file.path)); writeFile(ts.combinePaths(baseTestName, file.result.contentsPath), contents); const len = contents.length; if (len >= 2 && contents.charCodeAt(0) === 0xfeff) { @@ -235,8 +244,8 @@ namespace Playback { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i; - while (underlying.fileExists(fn() + ".json")) i++; - underlying.writeFile(ts.combinePaths(fn(), "test.json"), JSON.stringify(oldStyleLogIntoNewStyleLog(recordLog, (path, string) => underlying.writeFile(ts.combinePaths(fn(), path), string), fn()), null, 4)); // tslint:disable-line:no-null-keyword + while (underlying.fileExists(ts.combinePaths(fn(), "test.json"))) i++; + underlying.writeFile(ts.combinePaths(fn(), "test.json"), JSON.stringify(oldStyleLogIntoNewStyleLog(recordLog, (path, string) => underlying.writeFile(path, string), fn()), null, 4)); // tslint:disable-line:no-null-keyword recordLog = undefined; } }; @@ -415,4 +424,4 @@ namespace Playback { initWrapper(wrapper, underlying); return wrapper; } -} \ No newline at end of file +} From 79c672424e3183bb0b8e45c4992a92dd3f55c1fa Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 18 Oct 2017 15:32:24 -0700 Subject: [PATCH 225/246] Fix lint --- src/compiler/sys.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index c68292078cdcc..3ed80fbad391e 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -570,6 +570,7 @@ namespace ts { realpath }; } + function recursiveCreateDirectory(directoryPath: string, sys: System) { const basePath = getDirectoryPath(directoryPath); const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath); From 5fa8db55b23271ae1c1ce764152e127d1b0cf622 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 18 Oct 2017 15:46:09 -0700 Subject: [PATCH 226/246] Fix https://github.com/Microsoft/TypeScript/issues/19270: ensure output name is a valid locale name (#19308) * Fix https://github.com/Microsoft/TypeScript/issues/19270: ensure output name is a valid locale name * Use const instead of var * Add comment * Fix typo * Split the concat logic for generatedLCGFile --- Gulpfile.ts | 21 ++++++++-- Jakefile.js | 21 ++++++++-- .../generateLocalizedDiagnosticMessages.ts | 42 ++++++++++++++++++- 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/Gulpfile.ts b/Gulpfile.ts index 24ff1f3f3c9fe..200692b6ca42f 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -180,6 +180,23 @@ const libraryTargets = librarySourceMap.map(function(f) { return path.join(builtLocalDirectory, f.target); }); +/** + * .lcg file is what localization team uses to know what messages to localize. + * The file is always generated in 'enu\diagnosticMessages.generated.json.lcg' + */ +const generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); + +/** + * The localization target produces the two following transformations: + * 1. 'src\loc\lcl\\diagnosticMessages.generated.json.lcl' => 'built\local\\diagnosticMessages.generated.json' + * convert localized resources into a .json file the compiler can understand + * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' + * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json + */ +const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"].map(function (f) { + return path.join(builtLocalDirectory, f, "diagnosticMessages.generated.json"); +}).concat(generatedLCGFile); + for (const i in libraryTargets) { const entry = librarySourceMap[i]; const target = libraryTargets[i]; @@ -398,7 +415,6 @@ gulp.task(generateLocalizedDiagnosticMessagesJs, /*help*/ false, [], () => { }); // Localize diagnostics -const generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); gulp.task(generatedLCGFile, [generateLocalizedDiagnosticMessagesJs, diagnosticInfoMapTs], (done) => { if (fs.existsSync(builtLocalDirectory) && needsUpdate(generatedDiagnosticMessagesJSON, generatedLCGFile)) { exec(host, [generateLocalizedDiagnosticMessagesJs, lclDirectory, builtLocalDirectory, generatedDiagnosticMessagesJSON], done, done); @@ -576,8 +592,7 @@ gulp.task("dontUseDebugMode", /*help*/ false, [], (done) => { useDebugMode = fal gulp.task("VerifyLKG", /*help*/ false, [], () => { const expectedFiles = [builtLocalCompiler, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, typingsInstallerJs, cancellationTokenJs].concat(libraryTargets); const missingFiles = expectedFiles. - concat(fs.readdirSync(lclDirectory).map(function (d) { return path.join(builtLocalDirectory, d, "diagnosticMessages.generated.json"); })). - concat(generatedLCGFile). + concat(localizationTargets). filter(f => !fs.existsSync(f)); if (missingFiles.length > 0) { throw new Error("Cannot replace the LKG unless all built targets are present in directory " + builtLocalDirectory + diff --git a/Jakefile.js b/Jakefile.js index ba6943d30153d..06f13262a2841 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -239,6 +239,23 @@ var libraryTargets = librarySourceMap.map(function (f) { return path.join(builtLocalDirectory, f.target); }); +/** + * .lcg file is what localization team uses to know what messages to localize. + * The file is always generated in 'enu\diagnosticMessages.generated.json.lcg' + */ +var generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); + +/** + * The localization target produces the two following transformations: + * 1. 'src\loc\lcl\\diagnosticMessages.generated.json.lcl' => 'built\local\\diagnosticMessages.generated.json' + * convert localized resources into a .json file the compiler can understand + * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' + * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json + */ +var localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"].map(function (f) { + return path.join(builtLocalDirectory, f); +}).concat(path.dirname(generatedLCGFile)); + // Prepends the contents of prefixFile to destinationFile function prependFile(prefixFile, destinationFile) { if (!fs.existsSync(prefixFile)) { @@ -444,7 +461,6 @@ compileFile(generateLocalizedDiagnosticMessagesJs, /*useBuiltCompiler*/ false, { noOutFile: true, types: ["node", "xml2js"] }); // Localize diagnostics -var generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages.generated.json.lcg"); file(generatedLCGFile, [generateLocalizedDiagnosticMessagesJs, diagnosticInfoMapTs, generatedDiagnosticMessagesJSON], function () { var cmd = host + " " + generateLocalizedDiagnosticMessagesJs + " " + lclDirectory + " " + builtLocalDirectory + " " + generatedDiagnosticMessagesJSON; console.log(cmd); @@ -736,8 +752,7 @@ desc("Makes a new LKG out of the built js files"); task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () { var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts, watchGuardFile]. concat(libraryTargets). - concat(fs.readdirSync(lclDirectory).map(function (d) { return path.join(builtLocalDirectory, d) })). - concat(path.dirname(generatedLCGFile)); + concat(localizationTargets); var missingFiles = expectedFiles.filter(function (f) { return !fs.existsSync(f); }); diff --git a/scripts/generateLocalizedDiagnosticMessages.ts b/scripts/generateLocalizedDiagnosticMessages.ts index edfe957515516..d7d5f5c0e7969 100644 --- a/scripts/generateLocalizedDiagnosticMessages.ts +++ b/scripts/generateLocalizedDiagnosticMessages.ts @@ -27,16 +27,54 @@ function main(): void { function visitDirectory(name: string) { const inputFilePath = path.join(inputPath, name, "diagnosticMessages", "diagnosticMessages.generated.json.lcl"); - const outputFilePath = path.join(outputPath, name, "diagnosticMessages.generated.json"); + fs.readFile(inputFilePath, (err, data) => { handleError(err); xml2js.parseString(data.toString(), (err, result) => { handleError(err); - writeFile(outputFilePath, xmlObjectToString(result)); + if (!result || !result.LCX || !result.LCX.$ || !result.LCX.$.TgtCul) { + console.error("Unexpected XML file structure. Expected to find result.LCX.$.TgtCul."); + process.exit(1); + } + const outputDirectoryName = getPreferedLocaleName(result.LCX.$.TgtCul); + if (!outputDirectoryName) { + console.error(`Invalid output locale name for '${result.LCX.$.TgtCul}'.`); + process.exit(1); + } + writeFile(path.join(outputPath, outputDirectoryName, "diagnosticMessages.generated.json"), xmlObjectToString(result)); }); }); } + /** + * A locale name is based on the language tagging conventions of RFC 4646 (Windows Vista + * and later), and is represented by LOCALE_SNAME. + * Generally, the pattern - is used. Here, language is a lowercase ISO 639 + * language code. The codes from ISO 639-1 are used when available. Otherwise, codes from + * ISO 639-2/T are used. REGION specifies an uppercase ISO 3166-1 country/region identifier. + * For example, the locale name for English (United States) is "en-US" and the locale name + * for Divehi (Maldives) is "dv-MV". + * + * If the locale is a neutral locale (no region), the LOCALE_SNAME value follows the + * pattern . If it is a neutral locale for which the script is significant, the + * pattern is -