fix(33054): allow variables starting with an underscore in for/of statement (#36739)

This commit is contained in:
Alexander T 2020-03-30 21:18:18 +03:00 committed by GitHub
parent 96f01227d4
commit d8170faee1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 230 additions and 2 deletions

View File

@ -31013,6 +31013,18 @@ namespace ts {
return tryCast(getRootDeclaration(node), isParameter);
}
function isValidUnusedLocalDeclaration(declaration: Declaration): boolean {
if (isBindingElement(declaration) && isIdentifierThatStartsWithUnderscore(declaration.name)) {
return !!findAncestor(declaration.parent, ancestor =>
isArrayBindingPattern(ancestor) || isVariableDeclaration(ancestor) || isVariableDeclarationList(ancestor) ? false :
isForOfStatement(ancestor) ? true : "quit"
);
}
return isAmbientModule(declaration) ||
(isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!);
}
function checkUnusedLocalsAndParameters(nodeWithLocals: Node, addDiagnostic: AddUnusedDiagnostic): void {
// Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value.
const unusedImports = createMap<[ImportClause, ImportedDeclaration[]]>();
@ -31026,8 +31038,7 @@ namespace ts {
}
for (const declaration of local.declarations) {
if (isAmbientModule(declaration) ||
(isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!)) {
if (isValidUnusedLocalDeclaration(declaration)) {
continue;
}

View File

@ -0,0 +1,28 @@
//// [unusedVariablesWithUnderscoreInForOfLoop.ts]
function f() {
for (const [_a, b] of [['key', 1]]) {
console.log(b);
}
for (const [a, _b] of [['key', 1]]) {
console.log(a);
}
for (const [_a, _b] of [['key', 1]]) {}
}
//// [unusedVariablesWithUnderscoreInForOfLoop.js]
function f() {
for (var _i = 0, _c = [['key', 1]]; _i < _c.length; _i++) {
var _d = _c[_i], _a = _d[0], b = _d[1];
console.log(b);
}
for (var _e = 0, _f = [['key', 1]]; _e < _f.length; _e++) {
var _g = _f[_e], a = _g[0], _b = _g[1];
console.log(a);
}
for (var _h = 0, _j = [['key', 1]]; _h < _j.length; _h++) {
var _k = _j[_h], _a = _k[0], _b = _k[1];
}
}

View File

@ -0,0 +1,31 @@
=== tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop.ts ===
function f() {
>f : Symbol(f, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 0, 0))
for (const [_a, b] of [['key', 1]]) {
>_a : Symbol(_a, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 1, 16))
>b : Symbol(b, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 1, 19))
console.log(b);
>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, --, --))
>b : Symbol(b, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 1, 19))
}
for (const [a, _b] of [['key', 1]]) {
>a : Symbol(a, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 5, 16))
>_b : Symbol(_b, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 5, 18))
console.log(a);
>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, --, --))
>a : Symbol(a, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 5, 16))
}
for (const [_a, _b] of [['key', 1]]) {}
>_a : Symbol(_a, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 9, 16))
>_b : Symbol(_b, Decl(unusedVariablesWithUnderscoreInForOfLoop.ts, 9, 19))
}

View File

@ -0,0 +1,45 @@
=== tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop.ts ===
function f() {
>f : () => void
for (const [_a, b] of [['key', 1]]) {
>_a : string | number
>b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
console.log(b);
>console.log(b) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>b : string | number
}
for (const [a, _b] of [['key', 1]]) {
>a : string | number
>_b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
console.log(a);
>console.log(a) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>a : string | number
}
for (const [_a, _b] of [['key', 1]]) {}
>_a : string | number
>_b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
}

View File

@ -0,0 +1,23 @@
tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts(2,21): error TS6133: 'b' is declared but its value is never read.
tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts(4,17): error TS6133: 'a' is declared but its value is never read.
tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts(6,17): error TS6133: 'a' is declared but its value is never read.
tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts(6,20): error TS6133: 'b' is declared but its value is never read.
==== tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts (4 errors) ====
function f() {
for (const [_a, b] of [['key', 1]]) {}
~
!!! error TS6133: 'b' is declared but its value is never read.
for (const [a, _b] of [['key', 1]]) {}
~
!!! error TS6133: 'a' is declared but its value is never read.
for (const [a, b] of [['key', 1]]) {}
~
!!! error TS6133: 'a' is declared but its value is never read.
~
!!! error TS6133: 'b' is declared but its value is never read.
}

View File

@ -0,0 +1,22 @@
//// [unusedVariablesWithUnderscoreInForOfLoop1.ts]
function f() {
for (const [_a, b] of [['key', 1]]) {}
for (const [a, _b] of [['key', 1]]) {}
for (const [a, b] of [['key', 1]]) {}
}
//// [unusedVariablesWithUnderscoreInForOfLoop1.js]
function f() {
for (var _i = 0, _c = [['key', 1]]; _i < _c.length; _i++) {
var _d = _c[_i], _a = _d[0], b = _d[1];
}
for (var _e = 0, _f = [['key', 1]]; _e < _f.length; _e++) {
var _g = _f[_e], a = _g[0], _b = _g[1];
}
for (var _h = 0, _j = [['key', 1]]; _h < _j.length; _h++) {
var _k = _j[_h], a = _k[0], b = _k[1];
}
}

View File

@ -0,0 +1,17 @@
=== tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts ===
function f() {
>f : Symbol(f, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 0, 0))
for (const [_a, b] of [['key', 1]]) {}
>_a : Symbol(_a, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 1, 16))
>b : Symbol(b, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 1, 19))
for (const [a, _b] of [['key', 1]]) {}
>a : Symbol(a, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 3, 16))
>_b : Symbol(_b, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 3, 18))
for (const [a, b] of [['key', 1]]) {}
>a : Symbol(a, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 5, 16))
>b : Symbol(b, Decl(unusedVariablesWithUnderscoreInForOfLoop1.ts, 5, 18))
}

View File

@ -0,0 +1,29 @@
=== tests/cases/compiler/unusedVariablesWithUnderscoreInForOfLoop1.ts ===
function f() {
>f : () => void
for (const [_a, b] of [['key', 1]]) {}
>_a : string | number
>b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
for (const [a, _b] of [['key', 1]]) {}
>a : string | number
>_b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
for (const [a, b] of [['key', 1]]) {}
>a : string | number
>b : string | number
>[['key', 1]] : (string | number)[][]
>['key', 1] : (string | number)[]
>'key' : "key"
>1 : 1
}

View File

@ -0,0 +1,13 @@
//@noUnusedLocals:true
function f() {
for (const [_a, b] of [['key', 1]]) {
console.log(b);
}
for (const [a, _b] of [['key', 1]]) {
console.log(a);
}
for (const [_a, _b] of [['key', 1]]) {}
}

View File

@ -0,0 +1,9 @@
//@noUnusedLocals:true
function f() {
for (const [_a, b] of [['key', 1]]) {}
for (const [a, _b] of [['key', 1]]) {}
for (const [a, b] of [['key', 1]]) {}
}