From 9505a1889419a6ea22f6e0e972cdf462bd97f928 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 8 Dec 2016 14:35:35 -0800 Subject: [PATCH 1/2] Add tests when object spread is used in destructuring --- .../unusedLocalsAndObjectSpread.errors.txt | 27 ++++++++++++ .../reference/unusedLocalsAndObjectSpread.js | 42 +++++++++++++++++++ .../compiler/unusedLocalsAndObjectSpread.ts | 18 ++++++++ 3 files changed, 87 insertions(+) create mode 100644 tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt create mode 100644 tests/baselines/reference/unusedLocalsAndObjectSpread.js create mode 100644 tests/cases/compiler/unusedLocalsAndObjectSpread.ts diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt new file mode 100644 index 0000000000000..d46486245f1a5 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(7,12): error TS6133: 'a' is declared but never used. +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(14,15): error TS6133: '_' is declared but never used. + + +==== tests/cases/compiler/unusedLocalsAndObjectSpread.ts (2 errors) ==== + + declare var console: { log(a: any): void }; + + function one() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; + ~ +!!! error TS6133: 'a' is declared but never used. + console.log(bar); + } + + function two() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; + ~ +!!! error TS6133: '_' is declared but never used. + console.log(bar); + } + + \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.js b/tests/baselines/reference/unusedLocalsAndObjectSpread.js new file mode 100644 index 0000000000000..d75e3f160509f --- /dev/null +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.js @@ -0,0 +1,42 @@ +//// [unusedLocalsAndObjectSpread.ts] + +declare var console: { log(a: any): void }; + +function one() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; + console.log(bar); +} + +function two() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; + console.log(bar); +} + + + +//// [unusedLocalsAndObjectSpread.js] +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; +}; +function one() { + var foo = { a: 1, b: 2 }; + // 'a' is declared but never used + var a = foo.a, bar = __rest(foo, ["a"]); + console.log(bar); +} +function two() { + var foo = { a: 1, b: 2 }; + // '_' is declared but never used + var _ = foo.a, bar = __rest(foo, ["a"]); + console.log(bar); +} diff --git a/tests/cases/compiler/unusedLocalsAndObjectSpread.ts b/tests/cases/compiler/unusedLocalsAndObjectSpread.ts new file mode 100644 index 0000000000000..320873f93ffcc --- /dev/null +++ b/tests/cases/compiler/unusedLocalsAndObjectSpread.ts @@ -0,0 +1,18 @@ +//@noUnusedLocals:true + +declare var console: { log(a: any): void }; + +function one() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; + console.log(bar); +} + +function two() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; + console.log(bar); +} + From 81452c544a52b27ae82bc340178fe6db78fcfd5d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 8 Dec 2016 15:12:35 -0800 Subject: [PATCH 2/2] Do not report unused local error on locals that are intended for removing properties with object spread Fixes #12766 --- src/compiler/checker.ts | 13 +++++++++- .../unusedLocalsAndObjectSpread.errors.txt | 25 ++++++++++++++----- .../reference/unusedLocalsAndObjectSpread.js | 25 +++++++++++++++++++ .../compiler/unusedLocalsAndObjectSpread.ts | 13 ++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 778e31b9c5ba7..9512facfc5735 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16702,6 +16702,14 @@ namespace ts { } } + function isRemovedPropertyFromObjectSpread(node: Node) { + if (isBindingElement(node) && isObjectBindingPattern(node.parent)) { + const lastElement = lastOrUndefined(node.parent.elements); + return lastElement !== node && !!lastElement.dotDotDotToken; + } + return false; + } + function errorUnusedLocal(node: Node, name: string) { if (isIdentifierThatStartsWithUnderScore(node)) { const declaration = getRootDeclaration(node.parent); @@ -16711,7 +16719,10 @@ namespace ts { return; } } - error(node, Diagnostics._0_is_declared_but_never_used, name); + + if (!isRemovedPropertyFromObjectSpread(node.kind === SyntaxKind.Identifier ? node.parent : node)) { + error(node, Diagnostics._0_is_declared_but_never_used, name); + } } function parameterNameStartsWithUnderscore(parameterName: DeclarationName) { diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt index d46486245f1a5..56f2ba927fb70 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/unusedLocalsAndObjectSpread.ts(7,12): error TS6133: 'a' is declared but never used. -tests/cases/compiler/unusedLocalsAndObjectSpread.ts(14,15): error TS6133: '_' is declared but never used. +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(21,18): error TS6133: 'bar' is declared but never used. +tests/cases/compiler/unusedLocalsAndObjectSpread.ts(28,21): error TS6133: 'bar' is declared but never used. ==== tests/cases/compiler/unusedLocalsAndObjectSpread.ts (2 errors) ==== @@ -10,8 +10,6 @@ tests/cases/compiler/unusedLocalsAndObjectSpread.ts(14,15): error TS6133: '_' is const foo = { a: 1, b: 2 }; // 'a' is declared but never used const {a, ...bar} = foo; - ~ -!!! error TS6133: 'a' is declared but never used. console.log(bar); } @@ -19,9 +17,24 @@ tests/cases/compiler/unusedLocalsAndObjectSpread.ts(14,15): error TS6133: '_' is const foo = { a: 1, b: 2 }; // '_' is declared but never used const {a: _, ...bar} = foo; - ~ -!!! error TS6133: '_' is declared but never used. console.log(bar); } + function three() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; // bar should be unused + ~~~ +!!! error TS6133: 'bar' is declared but never used. + //console.log(bar); + } + + function four() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; // bar should be unused + ~~~ +!!! error TS6133: 'bar' is declared but never used. + //console.log(bar); + } \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsAndObjectSpread.js b/tests/baselines/reference/unusedLocalsAndObjectSpread.js index d75e3f160509f..2878f1b5c5c9b 100644 --- a/tests/baselines/reference/unusedLocalsAndObjectSpread.js +++ b/tests/baselines/reference/unusedLocalsAndObjectSpread.js @@ -16,6 +16,19 @@ function two() { console.log(bar); } +function three() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; // bar should be unused + //console.log(bar); +} + +function four() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; // bar should be unused + //console.log(bar); +} //// [unusedLocalsAndObjectSpread.js] @@ -40,3 +53,15 @@ function two() { var _ = foo.a, bar = __rest(foo, ["a"]); console.log(bar); } +function three() { + var foo = { a: 1, b: 2 }; + // 'a' is declared but never used + var a = foo.a, bar = __rest(foo, ["a"]); // bar should be unused + //console.log(bar); +} +function four() { + var foo = { a: 1, b: 2 }; + // '_' is declared but never used + var _ = foo.a, bar = __rest(foo, ["a"]); // bar should be unused + //console.log(bar); +} diff --git a/tests/cases/compiler/unusedLocalsAndObjectSpread.ts b/tests/cases/compiler/unusedLocalsAndObjectSpread.ts index 320873f93ffcc..b042b412c8e33 100644 --- a/tests/cases/compiler/unusedLocalsAndObjectSpread.ts +++ b/tests/cases/compiler/unusedLocalsAndObjectSpread.ts @@ -16,3 +16,16 @@ function two() { console.log(bar); } +function three() { + const foo = { a: 1, b: 2 }; + // 'a' is declared but never used + const {a, ...bar} = foo; // bar should be unused + //console.log(bar); +} + +function four() { + const foo = { a: 1, b: 2 }; + // '_' is declared but never used + const {a: _, ...bar} = foo; // bar should be unused + //console.log(bar); +}