From 026634fb95e0cb9ecdceb56e87105ec15f0e932c Mon Sep 17 00:00:00 2001 From: Lionel Besson Date: Tue, 13 Oct 2015 16:52:48 +0200 Subject: [PATCH] Fixes #727 --- src/language/utils.ts | 11 +++++-- src/rules/noShadowedVariableRule.ts | 30 +++++++++++++------ test/files/rules/no-shadowed-variable.test.ts | 14 +++++++++ test/rules/noShadowedVariableRuleTests.ts | 5 +++- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/language/utils.ts b/src/language/utils.ts index 50dbac8a7c3..9fdba79c8c9 100644 --- a/src/language/utils.ts +++ b/src/language/utils.ts @@ -97,16 +97,21 @@ export function isBlockScopedVariable(node: ts.VariableDeclaration | ts.Variable } export function isBlockScopedBindingElement(node: ts.BindingElement): boolean { + const variableDeclaration = getBindingElementVariableDeclaration(node); + // if no variable declaration, it must be a function param, which is block scoped + return (variableDeclaration == null) || isBlockScopedVariable(variableDeclaration); +} + +export function getBindingElementVariableDeclaration(node: ts.BindingElement): ts.VariableDeclaration { let currentParent = node.parent; while (currentParent.kind !== ts.SyntaxKind.VariableDeclaration) { if (currentParent.parent == null) { - // if we didn't encounter a VariableDeclaration, this must be a function parameter, which is block scoped - return true; + return null; // function parameter, no variable declaration } else { currentParent = currentParent.parent; } } - return isBlockScopedVariable( currentParent); + return currentParent; } /** diff --git a/src/rules/noShadowedVariableRule.ts b/src/rules/noShadowedVariableRule.ts index f105595a863..46b51a40975 100644 --- a/src/rules/noShadowedVariableRule.ts +++ b/src/rules/noShadowedVariableRule.ts @@ -36,10 +36,15 @@ class NoShadowedVariableWalker extends Lint.BlockScopeAwareRuleWalker node.name, isBlockScoped); + if (variableDeclaration) { + const isBlockScopedVariable = Lint.isBlockScopedVariable(variableDeclaration); + this.handleSingleVariableIdentifier( node.name, isBlockScopedVariable); + } else { + this.handleSingleParameterIdentifier( node.name); + } } super.visitBindingElement(node); @@ -64,15 +69,11 @@ class NoShadowedVariableWalker extends Lint.BlockScopeAwareRuleWalker node.name; - const variableName = variableIdentifier.text; - const currentScope = this.getCurrentScope(); + const isSingleParameter = node.name.kind === ts.SyntaxKind.Identifier; - if (this.isVarInAnyScope(variableName)) { - this.addFailureOnIdentifier(variableIdentifier); + if (isSingleParameter) { + this.handleSingleParameterIdentifier( node.name); } - currentScope.varNames.push(variableName); super.visitParameterDeclaration(node); } @@ -112,6 +113,17 @@ class NoShadowedVariableWalker extends Lint.BlockScopeAwareRuleWalker scopeInfo.varNames.indexOf(varName) >= 0); } diff --git a/test/files/rules/no-shadowed-variable.test.ts b/test/files/rules/no-shadowed-variable.test.ts index 126727bcb61..36b63434301 100644 --- a/test/files/rules/no-shadowed-variable.test.ts +++ b/test/files/rules/no-shadowed-variable.test.ts @@ -114,3 +114,17 @@ interface FalsePositive4 { (parameters: T, runSynchonous: boolean): TResult; (parameters: T, callback: (error: Error, result: TResult) => void): void; } + +let p = 1; +function testParameterDestructuring( + { pos: p }: FalsePositive3, // failure + { pos: q, specular: r }: FalsePositive3, + { pos }: FalsePositive3 +) { + p = 2; + var q = 1; // failure + + function someInnerFunc() { + let pos = 3; // failure + } +} diff --git a/test/rules/noShadowedVariableRuleTests.ts b/test/rules/noShadowedVariableRuleTests.ts index ba24cf86131..3d8911fca60 100644 --- a/test/rules/noShadowedVariableRuleTests.ts +++ b/test/rules/noShadowedVariableRuleTests.ts @@ -41,7 +41,10 @@ describe("", () => { Lint.Test.createFailure(fileName, [90, 16], [90, 17], NoShadowedVariableRule.FAILURE_STRING + "z'"), Lint.Test.createFailure(fileName, [94, 15], [94, 16], NoShadowedVariableRule.FAILURE_STRING + "x'"), Lint.Test.createFailure(fileName, [95, 15], [95, 16], NoShadowedVariableRule.FAILURE_STRING + "y'"), - Lint.Test.createFailure(fileName, [97, 17], [97, 18], NoShadowedVariableRule.FAILURE_STRING + "z'") + Lint.Test.createFailure(fileName, [97, 17], [97, 18], NoShadowedVariableRule.FAILURE_STRING + "z'"), + Lint.Test.createFailure(fileName, [120, 12], [120, 13], NoShadowedVariableRule.FAILURE_STRING + "p'"), + Lint.Test.createFailure(fileName, [125, 9], [125, 10], NoShadowedVariableRule.FAILURE_STRING + "q'"), + Lint.Test.createFailure(fileName, [128, 13], [128, 16], NoShadowedVariableRule.FAILURE_STRING + "pos'") ]; const actualFailures = Lint.Test.applyRuleOnFile(fileName, NoShadowedVariableRule);