From b227b4def32bfc57d282a1995fbf509f7a2d05b6 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 15 Jun 2017 14:00:44 -0700 Subject: [PATCH 1/8] Added a no-self-this rule Bans phrases like "var self = this;". Port of the [tslint-microsoft-contrib no-var-self rule](https://github.com/Microsoft/tslint-microsoft-contrib/blob/master/src/noVarSelfRule.ts). This commit does not yet add it to tslint:all. --- src/rules/noSelfThisRule.ts | 112 ++++++++++++++++++ .../allowed-this-names/test.ts.lint | 8 ++ .../allowed-this-names/tslint.json | 7 ++ test/rules/no-self-this/default/test.ts.lint | 33 ++++++ test/rules/no-self-this/default/tslint.json | 5 + 5 files changed, 165 insertions(+) create mode 100644 src/rules/noSelfThisRule.ts create mode 100644 test/rules/no-self-this/allowed-this-names/test.ts.lint create mode 100644 test/rules/no-self-this/allowed-this-names/tslint.json create mode 100644 test/rules/no-self-this/default/test.ts.lint create mode 100644 test/rules/no-self-this/default/tslint.json diff --git a/src/rules/noSelfThisRule.ts b/src/rules/noSelfThisRule.ts new file mode 100644 index 00000000000..df520598841 --- /dev/null +++ b/src/rules/noSelfThisRule.ts @@ -0,0 +1,112 @@ +/** + * @license + * Copyright 2017 Palantir Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as utils from "tsutils"; +import * as ts from "typescript"; + +import * as Lint from "../index"; + +const ALLOWED_THIS_NAMES = "allowed-this-names"; + +interface Options { + allowedThisNames: string[]; +} + +type RuleArgument = boolean | { + "allowed-this-names": string[]; +}; + +export class Rule extends Lint.Rules.AbstractRule { + public static metadata: Lint.IRuleMetadata = { + description: "Disallows unnecessary references to `this`.", + optionExamples: [ + true, + [ + true, + { + [ALLOWED_THIS_NAMES]: ["self"], + }, + ], + ], + options: { + listType: "string", + type: "list", + }, + optionsDescription: Lint.Utils.dedent` + \`${ALLOWED_THIS_NAMES}\` may be specified as a list of regular expressions to match allowed variable names.`, + rationale: "Assigning a variable to `this` instead of properly using arrow lambdas" + + "may be a symptom of pre-ES6 practices or not manging scope well.", + ruleName: "no-self-this", + type: "functionality", + typescriptOnly: false, + }; + + public static FAILURE_STRING_FACTORY(name: string) { + return `Assigning \`this\` reference to local variable not allowed: ${name}.`; + } + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const allowedThisNames: string[] = []; + + for (const ruleArgument of this.ruleArguments as RuleArgument[]) { + if (typeof ruleArgument === "object" && ruleArgument[ALLOWED_THIS_NAMES] !== undefined) { + allowedThisNames.push(...ruleArgument[ALLOWED_THIS_NAMES]); + } + } + + const noSelfThisWalker = new NoSelfThisWalker(sourceFile, this.ruleName, { allowedThisNames }); + + return this.applyWithWalker(noSelfThisWalker); + } +} + +class NoSelfThisWalker extends Lint.AbstractWalker { + private readonly allowedThisNameTesters = this.options.allowedThisNames.map( + (allowedThisName) => new RegExp(allowedThisName)); + + public walk(sourceFile: ts.SourceFile): void { + ts.forEachChild(sourceFile, this.visitNode); + } + + private visitNode = (node: ts.Node): void => { + if (utils.isVariableDeclaration(node)) { + this.visitVariableDeclaration(node); + } + + ts.forEachChild(node, this.visitNode); + } + + private visitVariableDeclaration(node: ts.VariableDeclaration): void { + if (node.initializer !== undefined + && node.initializer.kind === ts.SyntaxKind.ThisKeyword + && node.name.kind === ts.SyntaxKind.Identifier + && this.variableNameIsBanned(node.name.text) + ) { + this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING_FACTORY(node.name.text)); + } + } + + private variableNameIsBanned(name: string): boolean { + for (const tester of this.allowedThisNameTesters) { + if (tester.test(name)) { + return false; + } + } + + return true; + } +} diff --git a/test/rules/no-self-this/allowed-this-names/test.ts.lint b/test/rules/no-self-this/allowed-this-names/test.ts.lint new file mode 100644 index 00000000000..7411f550af8 --- /dev/null +++ b/test/rules/no-self-this/allowed-this-names/test.ts.lint @@ -0,0 +1,8 @@ +const start = this; + +const startEnd = this; + +const endStart = this; + ~~~~~~~~~~~~~~~ [name % ('endStart')] + +[name]: Assigning `this` reference to local variable not allowed: %s. diff --git a/test/rules/no-self-this/allowed-this-names/tslint.json b/test/rules/no-self-this/allowed-this-names/tslint.json new file mode 100644 index 00000000000..c7f6c820cab --- /dev/null +++ b/test/rules/no-self-this/allowed-this-names/tslint.json @@ -0,0 +1,7 @@ +{ + "rules": { + "no-self-this": [true, { + "allowed-this-names": ["^start"] + }] + } +} diff --git a/test/rules/no-self-this/default/test.ts.lint b/test/rules/no-self-this/default/test.ts.lint new file mode 100644 index 00000000000..5e976fded14 --- /dev/null +++ b/test/rules/no-self-this/default/test.ts.lint @@ -0,0 +1,33 @@ +var unscoped = this; + ~~~~~~~~~~~~~~~ [name % ('unscoped')] + +function testFunction() { + let inFunction = this; + ~~~~~~~~~~~~~~~~~ [name % ('inFunction')] +} + +const testLambda = () => { + const inLambda = this; + ~~~~~~~~~~~~~~~ [name % ('inLambda')] +}; + +class TestClass { + constructor() { + const inConstructor = this; + ~~~~~~~~~~~~~~~~~~~~ [name % ('inConstructor')] + + const asThis: this = this; + ~~~~~~~~~~~~~~~~~~~ [name % ('asThis')] + + const asString = "this"; + const asArray = [this]; + const asArrayString = ["this"]; + } + + public act(scope: this = this) { + const inMemberFunction = this; + ~~~~~~~~~~~~~~~~~~~~~~~ [name % ('inMemberFunction')] + } +} + +[name]: Assigning `this` reference to local variable not allowed: %s. diff --git a/test/rules/no-self-this/default/tslint.json b/test/rules/no-self-this/default/tslint.json new file mode 100644 index 00000000000..db740c2467f --- /dev/null +++ b/test/rules/no-self-this/default/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-self-this": true + } +} From 9ae9983ed6e6cc57995cea2ca0b7640bfbf6def3 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 15 Jun 2017 14:03:58 -0700 Subject: [PATCH 2/8] Added no-self-this to tslint:all No violations in the code base --- src/configs/all.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/configs/all.ts b/src/configs/all.ts index f4dff8e4daa..e84bb750ed1 100644 --- a/src/configs/all.ts +++ b/src/configs/all.ts @@ -51,6 +51,7 @@ export const rules = { "no-namespace": true, "no-non-null-assertion": true, "no-reference": true, + "no-self-this": true, "no-var-requires": true, "only-arrow-functions": true, "prefer-for-of": true, From eee701453778251383b594f5e34fdca0cfae6a95 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 17 Jun 2017 21:01:35 -0700 Subject: [PATCH 3/8] Renamed no-self-this to no-this-reassignment --- src/configs/all.ts | 2 +- src/rules/noShadowedVariableRule.ts | 157 ------------------ ...fThisRule.ts => noThisReassignmentRule.ts} | 10 +- .../allowed-this-names/test.ts.lint | 0 .../allowed-this-names/tslint.json | 2 +- .../default/test.ts.lint | 0 .../no-self-reassignment/default/tslint.json | 5 + test/rules/no-self-this/default/tslint.json | 5 - 8 files changed, 12 insertions(+), 169 deletions(-) delete mode 100644 src/rules/noShadowedVariableRule.ts rename src/rules/{noSelfThisRule.ts => noThisReassignmentRule.ts} (89%) rename test/rules/{no-self-this => no-self-reassignment}/allowed-this-names/test.ts.lint (100%) rename test/rules/{no-self-this => no-self-reassignment}/allowed-this-names/tslint.json (64%) rename test/rules/{no-self-this => no-self-reassignment}/default/test.ts.lint (100%) create mode 100644 test/rules/no-self-reassignment/default/tslint.json delete mode 100644 test/rules/no-self-this/default/tslint.json diff --git a/src/configs/all.ts b/src/configs/all.ts index e84bb750ed1..bc3d2cf99b4 100644 --- a/src/configs/all.ts +++ b/src/configs/all.ts @@ -51,7 +51,7 @@ export const rules = { "no-namespace": true, "no-non-null-assertion": true, "no-reference": true, - "no-self-this": true, + "no-this-reassignment": true, "no-var-requires": true, "only-arrow-functions": true, "prefer-for-of": true, diff --git a/src/rules/noShadowedVariableRule.ts b/src/rules/noShadowedVariableRule.ts deleted file mode 100644 index d425cba5c54..00000000000 --- a/src/rules/noShadowedVariableRule.ts +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @license - * Copyright 2013 Palantir Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// tslint:disable deprecation -// (https://github.com/palantir/tslint/pull/2598) - -import * as ts from "typescript"; - -import * as Lint from "../index"; - -export class Rule extends Lint.Rules.AbstractRule { - /* tslint:disable:object-literal-sort-keys */ - public static metadata: Lint.IRuleMetadata = { - ruleName: "no-shadowed-variable", - description: "Disallows shadowing variable declarations.", - rationale: "Shadowing a variable masks access to it and obscures to what value an identifier actually refers.", - optionsDescription: "Not configurable.", - options: null, - optionExamples: [true], - type: "functionality", - typescriptOnly: false, - }; - /* tslint:enable:object-literal-sort-keys */ - - public static FAILURE_STRING_FACTORY(name: string) { - return `Shadowed variable: '${name}'`; - } - - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new NoShadowedVariableWalker(sourceFile, this.getOptions())); - } -} - -class NoShadowedVariableWalker extends Lint.BlockScopeAwareRuleWalker, Set> { - public createScope() { - return new Set(); - } - - public createBlockScope() { - return new Set(); - } - - public visitBindingElement(node: ts.BindingElement) { - const isSingleVariable = node.name.kind === ts.SyntaxKind.Identifier; - if (isSingleVariable) { - const name = node.name as ts.Identifier; - const variableDeclaration = Lint.getBindingElementVariableDeclaration(node); - const isBlockScopedVariable = variableDeclaration !== null && Lint.isBlockScopedVariable(variableDeclaration); - this.handleSingleVariableIdentifier(name, isBlockScopedVariable); - } - - super.visitBindingElement(node); - } - - public visitCatchClause(node: ts.CatchClause) { - // don't visit the catch clause variable declaration, just visit the block - // the catch clause variable declaration has its own special scoping rules - this.visitBlock(node.block); - } - - public visitCallSignature(_node: ts.SignatureDeclaration) { - // don't call super, we don't need to check parameter names in call signatures - } - - public visitFunctionType(_node: ts.FunctionOrConstructorTypeNode) { - // don't call super, we don't need to check names in function types - } - - public visitConstructorType(_node: ts.FunctionOrConstructorTypeNode) { - // don't call super, we don't need to check names in constructor types - } - - public visitIndexSignatureDeclaration(_node: ts.SignatureDeclaration) { - // don't call super, we don't want to walk index signatures - } - - public visitMethodSignature(_node: ts.SignatureDeclaration) { - // don't call super, we don't want to walk method signatures either - } - - public visitParameterDeclaration(node: ts.ParameterDeclaration) { - const isSingleParameter = node.name.kind === ts.SyntaxKind.Identifier; - - if (isSingleParameter) { - this.handleSingleVariableIdentifier(node.name as ts.Identifier, false); - } - - super.visitParameterDeclaration(node); - } - - public visitTypeLiteral(_node: ts.TypeLiteralNode) { - // don't call super, we don't want to walk the inside of type nodes - } - - public visitVariableDeclaration(node: ts.VariableDeclaration) { - const isSingleVariable = node.name.kind === ts.SyntaxKind.Identifier; - - if (isSingleVariable) { - this.handleSingleVariableIdentifier(node.name as ts.Identifier, Lint.isBlockScopedVariable(node)); - } - - super.visitVariableDeclaration(node); - } - - private handleSingleVariableIdentifier(variableIdentifier: ts.Identifier, isBlockScoped: boolean) { - const variableName = variableIdentifier.text; - - if (this.isVarInCurrentScope(variableName) && !this.inCurrentBlockScope(variableName)) { - // shadowing if there's already a `var` of the same name in the scope AND - // it's not in the current block (handled by the 'no-duplicate-variable' rule) - this.addFailureOnIdentifier(variableIdentifier); - } else if (this.inPreviousBlockScope(variableName)) { - // shadowing if there is a `var`, `let`, 'const`, or parameter in a previous block scope - this.addFailureOnIdentifier(variableIdentifier); - } - - if (!isBlockScoped) { - // `var` variables go on the scope - this.getCurrentScope().add(variableName); - } - // all variables go on block scope, including `var` - this.getCurrentBlockScope().add(variableName); - } - - private isVarInCurrentScope(varName: string) { - return this.getCurrentScope().has(varName); - } - - private inCurrentBlockScope(varName: string) { - return this.getCurrentBlockScope().has(varName); - } - - private inPreviousBlockScope(varName: string) { - return this.getAllBlockScopes().some((scopeInfo) => { - return scopeInfo !== this.getCurrentBlockScope() && scopeInfo.has(varName); - }); - } - - private addFailureOnIdentifier(ident: ts.Identifier) { - const failureString = Rule.FAILURE_STRING_FACTORY(ident.text); - this.addFailureAtNode(ident, failureString); - } -} diff --git a/src/rules/noSelfThisRule.ts b/src/rules/noThisReassignmentRule.ts similarity index 89% rename from src/rules/noSelfThisRule.ts rename to src/rules/noThisReassignmentRule.ts index df520598841..1f6f48a50db 100644 --- a/src/rules/noSelfThisRule.ts +++ b/src/rules/noThisReassignmentRule.ts @@ -50,7 +50,7 @@ export class Rule extends Lint.Rules.AbstractRule { \`${ALLOWED_THIS_NAMES}\` may be specified as a list of regular expressions to match allowed variable names.`, rationale: "Assigning a variable to `this` instead of properly using arrow lambdas" + "may be a symptom of pre-ES6 practices or not manging scope well.", - ruleName: "no-self-this", + ruleName: "no-this-reassignment", type: "functionality", typescriptOnly: false, }; @@ -68,13 +68,13 @@ export class Rule extends Lint.Rules.AbstractRule { } } - const noSelfThisWalker = new NoSelfThisWalker(sourceFile, this.ruleName, { allowedThisNames }); + const noThisReassignmentWalker = new NoThisReassignmentWalker(sourceFile, this.ruleName, { allowedThisNames }); - return this.applyWithWalker(noSelfThisWalker); + return this.applyWithWalker(noThisReassignmentWalker); } } -class NoSelfThisWalker extends Lint.AbstractWalker { +class NoThisReassignmentWalker extends Lint.AbstractWalker { private readonly allowedThisNameTesters = this.options.allowedThisNames.map( (allowedThisName) => new RegExp(allowedThisName)); @@ -96,7 +96,7 @@ class NoSelfThisWalker extends Lint.AbstractWalker { && node.name.kind === ts.SyntaxKind.Identifier && this.variableNameIsBanned(node.name.text) ) { - this.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_STRING_FACTORY(node.name.text)); + this.addFailureAtNode(node, Rule.FAILURE_STRING_FACTORY(node.name.text)); } } diff --git a/test/rules/no-self-this/allowed-this-names/test.ts.lint b/test/rules/no-self-reassignment/allowed-this-names/test.ts.lint similarity index 100% rename from test/rules/no-self-this/allowed-this-names/test.ts.lint rename to test/rules/no-self-reassignment/allowed-this-names/test.ts.lint diff --git a/test/rules/no-self-this/allowed-this-names/tslint.json b/test/rules/no-self-reassignment/allowed-this-names/tslint.json similarity index 64% rename from test/rules/no-self-this/allowed-this-names/tslint.json rename to test/rules/no-self-reassignment/allowed-this-names/tslint.json index c7f6c820cab..8b9c2aa18bf 100644 --- a/test/rules/no-self-this/allowed-this-names/tslint.json +++ b/test/rules/no-self-reassignment/allowed-this-names/tslint.json @@ -1,6 +1,6 @@ { "rules": { - "no-self-this": [true, { + "no-this-reassignment": [true, { "allowed-this-names": ["^start"] }] } diff --git a/test/rules/no-self-this/default/test.ts.lint b/test/rules/no-self-reassignment/default/test.ts.lint similarity index 100% rename from test/rules/no-self-this/default/test.ts.lint rename to test/rules/no-self-reassignment/default/test.ts.lint diff --git a/test/rules/no-self-reassignment/default/tslint.json b/test/rules/no-self-reassignment/default/tslint.json new file mode 100644 index 00000000000..86df1b9b6a8 --- /dev/null +++ b/test/rules/no-self-reassignment/default/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-this-reassignment": true + } +} diff --git a/test/rules/no-self-this/default/tslint.json b/test/rules/no-self-this/default/tslint.json deleted file mode 100644 index db740c2467f..00000000000 --- a/test/rules/no-self-this/default/tslint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "no-self-this": true - } -} From 6bc6a1e37801d725d1b446dd05673c3d9f7bab42 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 17 Jun 2017 21:02:54 -0700 Subject: [PATCH 4/8] Re-aded missing noShadowedVariableRule.ts --- src/rules/noShadowedVariableRule.ts | 157 ++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/rules/noShadowedVariableRule.ts diff --git a/src/rules/noShadowedVariableRule.ts b/src/rules/noShadowedVariableRule.ts new file mode 100644 index 00000000000..d425cba5c54 --- /dev/null +++ b/src/rules/noShadowedVariableRule.ts @@ -0,0 +1,157 @@ +/** + * @license + * Copyright 2013 Palantir Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// tslint:disable deprecation +// (https://github.com/palantir/tslint/pull/2598) + +import * as ts from "typescript"; + +import * as Lint from "../index"; + +export class Rule extends Lint.Rules.AbstractRule { + /* tslint:disable:object-literal-sort-keys */ + public static metadata: Lint.IRuleMetadata = { + ruleName: "no-shadowed-variable", + description: "Disallows shadowing variable declarations.", + rationale: "Shadowing a variable masks access to it and obscures to what value an identifier actually refers.", + optionsDescription: "Not configurable.", + options: null, + optionExamples: [true], + type: "functionality", + typescriptOnly: false, + }; + /* tslint:enable:object-literal-sort-keys */ + + public static FAILURE_STRING_FACTORY(name: string) { + return `Shadowed variable: '${name}'`; + } + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithWalker(new NoShadowedVariableWalker(sourceFile, this.getOptions())); + } +} + +class NoShadowedVariableWalker extends Lint.BlockScopeAwareRuleWalker, Set> { + public createScope() { + return new Set(); + } + + public createBlockScope() { + return new Set(); + } + + public visitBindingElement(node: ts.BindingElement) { + const isSingleVariable = node.name.kind === ts.SyntaxKind.Identifier; + if (isSingleVariable) { + const name = node.name as ts.Identifier; + const variableDeclaration = Lint.getBindingElementVariableDeclaration(node); + const isBlockScopedVariable = variableDeclaration !== null && Lint.isBlockScopedVariable(variableDeclaration); + this.handleSingleVariableIdentifier(name, isBlockScopedVariable); + } + + super.visitBindingElement(node); + } + + public visitCatchClause(node: ts.CatchClause) { + // don't visit the catch clause variable declaration, just visit the block + // the catch clause variable declaration has its own special scoping rules + this.visitBlock(node.block); + } + + public visitCallSignature(_node: ts.SignatureDeclaration) { + // don't call super, we don't need to check parameter names in call signatures + } + + public visitFunctionType(_node: ts.FunctionOrConstructorTypeNode) { + // don't call super, we don't need to check names in function types + } + + public visitConstructorType(_node: ts.FunctionOrConstructorTypeNode) { + // don't call super, we don't need to check names in constructor types + } + + public visitIndexSignatureDeclaration(_node: ts.SignatureDeclaration) { + // don't call super, we don't want to walk index signatures + } + + public visitMethodSignature(_node: ts.SignatureDeclaration) { + // don't call super, we don't want to walk method signatures either + } + + public visitParameterDeclaration(node: ts.ParameterDeclaration) { + const isSingleParameter = node.name.kind === ts.SyntaxKind.Identifier; + + if (isSingleParameter) { + this.handleSingleVariableIdentifier(node.name as ts.Identifier, false); + } + + super.visitParameterDeclaration(node); + } + + public visitTypeLiteral(_node: ts.TypeLiteralNode) { + // don't call super, we don't want to walk the inside of type nodes + } + + public visitVariableDeclaration(node: ts.VariableDeclaration) { + const isSingleVariable = node.name.kind === ts.SyntaxKind.Identifier; + + if (isSingleVariable) { + this.handleSingleVariableIdentifier(node.name as ts.Identifier, Lint.isBlockScopedVariable(node)); + } + + super.visitVariableDeclaration(node); + } + + private handleSingleVariableIdentifier(variableIdentifier: ts.Identifier, isBlockScoped: boolean) { + const variableName = variableIdentifier.text; + + if (this.isVarInCurrentScope(variableName) && !this.inCurrentBlockScope(variableName)) { + // shadowing if there's already a `var` of the same name in the scope AND + // it's not in the current block (handled by the 'no-duplicate-variable' rule) + this.addFailureOnIdentifier(variableIdentifier); + } else if (this.inPreviousBlockScope(variableName)) { + // shadowing if there is a `var`, `let`, 'const`, or parameter in a previous block scope + this.addFailureOnIdentifier(variableIdentifier); + } + + if (!isBlockScoped) { + // `var` variables go on the scope + this.getCurrentScope().add(variableName); + } + // all variables go on block scope, including `var` + this.getCurrentBlockScope().add(variableName); + } + + private isVarInCurrentScope(varName: string) { + return this.getCurrentScope().has(varName); + } + + private inCurrentBlockScope(varName: string) { + return this.getCurrentBlockScope().has(varName); + } + + private inPreviousBlockScope(varName: string) { + return this.getAllBlockScopes().some((scopeInfo) => { + return scopeInfo !== this.getCurrentBlockScope() && scopeInfo.has(varName); + }); + } + + private addFailureOnIdentifier(ident: ts.Identifier) { + const failureString = Rule.FAILURE_STRING_FACTORY(ident.text); + this.addFailureAtNode(ident, failureString); + } +} From 1b3fb4b07b446be77292915e6d62a1eb2d34d7cb Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 17 Jun 2017 22:36:47 -0700 Subject: [PATCH 5/8] Added an allow-this-destructuring Also fixed tests to be under the right name... --- src/rules/noThisReassignmentRule.ts | 61 ++++++++++++++----- .../no-self-reassignment/default/test.ts.lint | 33 ---------- .../allow-this-destructuring/test.ts.lint | 3 + .../allow-this-destructuring/tslint.json | 7 +++ .../allowed-this-names/test.ts.lint | 0 .../allowed-this-names/tslint.json | 0 .../no-this-reassignment/default/test.ts.lint | 40 ++++++++++++ .../default/tslint.json | 0 8 files changed, 97 insertions(+), 47 deletions(-) delete mode 100644 test/rules/no-self-reassignment/default/test.ts.lint create mode 100644 test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint create mode 100644 test/rules/no-this-reassignment/allow-this-destructuring/tslint.json rename test/rules/{no-self-reassignment => no-this-reassignment}/allowed-this-names/test.ts.lint (100%) rename test/rules/{no-self-reassignment => no-this-reassignment}/allowed-this-names/tslint.json (100%) create mode 100644 test/rules/no-this-reassignment/default/test.ts.lint rename test/rules/{no-self-reassignment => no-this-reassignment}/default/tslint.json (100%) diff --git a/src/rules/noThisReassignmentRule.ts b/src/rules/noThisReassignmentRule.ts index 1f6f48a50db..c66eaab3369 100644 --- a/src/rules/noThisReassignmentRule.ts +++ b/src/rules/noThisReassignmentRule.ts @@ -20,14 +20,17 @@ import * as ts from "typescript"; import * as Lint from "../index"; +const ALLOW_THIS_DESTRUCTURING = "allow-this-destructuring"; const ALLOWED_THIS_NAMES = "allowed-this-names"; interface Options { allowedThisNames: string[]; + allowThisDestructuring: boolean; } type RuleArgument = boolean | { - "allowed-this-names": string[]; + "allow-this-destructuring"?: boolean; + "allowed-this-names"?: string[]; }; export class Rule extends Lint.Rules.AbstractRule { @@ -39,15 +42,28 @@ export class Rule extends Lint.Rules.AbstractRule { true, { [ALLOWED_THIS_NAMES]: ["self"], + [ALLOW_THIS_DESTRUCTURING]: true, }, ], ], options: { - listType: "string", - type: "list", + additionalProperties: false, + properties: { + [ALLOW_THIS_DESTRUCTURING]: { + type: "boolean", + }, + [ALLOWED_THIS_NAMES]: { + listType: "string", + type: "list", + }, + }, + type: "object", }, optionsDescription: Lint.Utils.dedent` - \`${ALLOWED_THIS_NAMES}\` may be specified as a list of regular expressions to match allowed variable names.`, + Two options may be provided on an object: + + * \`${ALLOW_THIS_DESTRUCTURING}\` allows using destructuring to access members of \`this\` (e.g. \`{ foo, bar } = this;\`). + * \`${ALLOWED_THIS_NAMES}\` may be specified as a list of regular expressions to match allowed variable names.`, rationale: "Assigning a variable to `this` instead of properly using arrow lambdas" + "may be a symptom of pre-ES6 practices or not manging scope well.", ruleName: "no-this-reassignment", @@ -55,20 +71,28 @@ export class Rule extends Lint.Rules.AbstractRule { typescriptOnly: false, }; - public static FAILURE_STRING_FACTORY(name: string) { + public static readonly FAILURE_STRING_BINDINGS = "Don't reassign members of `this` to local variables."; + + public static FAILURE_STRING_FACTORY_IDENTIFIERS(name: string) { return `Assigning \`this\` reference to local variable not allowed: ${name}.`; } public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const allowedThisNames: string[] = []; + let allowThisDestructuring = false; for (const ruleArgument of this.ruleArguments as RuleArgument[]) { - if (typeof ruleArgument === "object" && ruleArgument[ALLOWED_THIS_NAMES] !== undefined) { - allowedThisNames.push(...ruleArgument[ALLOWED_THIS_NAMES]); + if (typeof ruleArgument === "object") { + allowThisDestructuring = !!ruleArgument[ALLOW_THIS_DESTRUCTURING]; + + if (ruleArgument[ALLOWED_THIS_NAMES] !== undefined) { + allowedThisNames.push(...ruleArgument[ALLOWED_THIS_NAMES]!); + } } } - const noThisReassignmentWalker = new NoThisReassignmentWalker(sourceFile, this.ruleName, { allowedThisNames }); + const options = { allowedThisNames, allowThisDestructuring }; + const noThisReassignmentWalker = new NoThisReassignmentWalker(sourceFile, this.ruleName, options); return this.applyWithWalker(noThisReassignmentWalker); } @@ -91,12 +115,21 @@ class NoThisReassignmentWalker extends Lint.AbstractWalker { } private visitVariableDeclaration(node: ts.VariableDeclaration): void { - if (node.initializer !== undefined - && node.initializer.kind === ts.SyntaxKind.ThisKeyword - && node.name.kind === ts.SyntaxKind.Identifier - && this.variableNameIsBanned(node.name.text) - ) { - this.addFailureAtNode(node, Rule.FAILURE_STRING_FACTORY(node.name.text)); + if (node.initializer === undefined || node.initializer.kind !== ts.SyntaxKind.ThisKeyword) { + return; + } + + switch (node.name.kind) { + case ts.SyntaxKind.Identifier: + if (this.variableNameIsBanned(node.name.text)) { + this.addFailureAtNode(node, Rule.FAILURE_STRING_FACTORY_IDENTIFIERS(node.name.text)); + } + break; + + case ts.SyntaxKind.ObjectBindingPattern: + if (!this.options.allowThisDestructuring) { + this.addFailureAtNode(node, Rule.FAILURE_STRING_BINDINGS); + } } } diff --git a/test/rules/no-self-reassignment/default/test.ts.lint b/test/rules/no-self-reassignment/default/test.ts.lint deleted file mode 100644 index 5e976fded14..00000000000 --- a/test/rules/no-self-reassignment/default/test.ts.lint +++ /dev/null @@ -1,33 +0,0 @@ -var unscoped = this; - ~~~~~~~~~~~~~~~ [name % ('unscoped')] - -function testFunction() { - let inFunction = this; - ~~~~~~~~~~~~~~~~~ [name % ('inFunction')] -} - -const testLambda = () => { - const inLambda = this; - ~~~~~~~~~~~~~~~ [name % ('inLambda')] -}; - -class TestClass { - constructor() { - const inConstructor = this; - ~~~~~~~~~~~~~~~~~~~~ [name % ('inConstructor')] - - const asThis: this = this; - ~~~~~~~~~~~~~~~~~~~ [name % ('asThis')] - - const asString = "this"; - const asArray = [this]; - const asArrayString = ["this"]; - } - - public act(scope: this = this) { - const inMemberFunction = this; - ~~~~~~~~~~~~~~~~~~~~~~~ [name % ('inMemberFunction')] - } -} - -[name]: Assigning `this` reference to local variable not allowed: %s. diff --git a/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint b/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint new file mode 100644 index 00000000000..862a6ffc4fe --- /dev/null +++ b/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint @@ -0,0 +1,3 @@ +const { length } = this; + +const { length, toString } = this; diff --git a/test/rules/no-this-reassignment/allow-this-destructuring/tslint.json b/test/rules/no-this-reassignment/allow-this-destructuring/tslint.json new file mode 100644 index 00000000000..06c9eb5424e --- /dev/null +++ b/test/rules/no-this-reassignment/allow-this-destructuring/tslint.json @@ -0,0 +1,7 @@ +{ + "rules": { + "no-this-reassignment": [true, { + "allow-this-destructuring": true + }] + } +} diff --git a/test/rules/no-self-reassignment/allowed-this-names/test.ts.lint b/test/rules/no-this-reassignment/allowed-this-names/test.ts.lint similarity index 100% rename from test/rules/no-self-reassignment/allowed-this-names/test.ts.lint rename to test/rules/no-this-reassignment/allowed-this-names/test.ts.lint diff --git a/test/rules/no-self-reassignment/allowed-this-names/tslint.json b/test/rules/no-this-reassignment/allowed-this-names/tslint.json similarity index 100% rename from test/rules/no-self-reassignment/allowed-this-names/tslint.json rename to test/rules/no-this-reassignment/allowed-this-names/tslint.json diff --git a/test/rules/no-this-reassignment/default/test.ts.lint b/test/rules/no-this-reassignment/default/test.ts.lint new file mode 100644 index 00000000000..3af626180d0 --- /dev/null +++ b/test/rules/no-this-reassignment/default/test.ts.lint @@ -0,0 +1,40 @@ +var unscoped = this; + ~~~~~~~~~~~~~~~ [identifier % ('unscoped')] + +function testFunction() { + let inFunction = this; + ~~~~~~~~~~~~~~~~~ [identifier % ('inFunction')] +} + +const testLambda = () => { + const inLambda = this; + ~~~~~~~~~~~~~~~ [identifier % ('inLambda')] +}; + +class TestClass { + constructor() { + const inConstructor = this; + ~~~~~~~~~~~~~~~~~~~~ [identifier % ('inConstructor')] + + const asThis: this = this; + ~~~~~~~~~~~~~~~~~~~ [identifier % ('asThis')] + + const asString = "this"; + const asArray = [this]; + const asArrayString = ["this"]; + } + + public act(scope: this = this) { + const inMemberFunction = this; + ~~~~~~~~~~~~~~~~~~~~~~~ [identifier % ('inMemberFunction')] + + const { act } = this; + ~~~~~~~~~~~~~~ [binding] + + const { act, constructor } = this; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ [binding] + } +} + +[binding]: Don't reassign members of `this` to local variables. +[identifier]: Assigning `this` reference to local variable not allowed: %s. diff --git a/test/rules/no-self-reassignment/default/tslint.json b/test/rules/no-this-reassignment/default/tslint.json similarity index 100% rename from test/rules/no-self-reassignment/default/tslint.json rename to test/rules/no-this-reassignment/default/tslint.json From 9aaea51710628ebb204be7765719920baf2ee71f Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 18 Jun 2017 01:21:49 -0700 Subject: [PATCH 6/8] Missing base case in destructuring test --- .../allow-this-destructuring/test.ts.lint | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint b/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint index 862a6ffc4fe..7a13bab49be 100644 --- a/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint +++ b/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint @@ -1,3 +1,9 @@ const { length } = this; const { length, toString } = this; + +const self = this; + ~~~~~~~~~~~ [name % ('self')] + +[name]: Assigning `this` reference to local variable not allowed: %s. + From 63e4300a078a03cb6ff11a4d9bff17d2ef3cb6df Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 18 Jun 2017 15:35:52 -0700 Subject: [PATCH 7/8] Feedback: "this" in options; array destructuring Also not using a for loop for options and added to :latest. --- src/configs/latest.ts | 1 + src/rules/noThisReassignmentRule.ts | 54 ++++++++++--------- .../test.ts.lint | 4 ++ .../tslint.json | 2 +- .../test.ts.lint | 0 .../tslint.json | 2 +- .../no-this-reassignment/default/test.ts.lint | 8 ++- 7 files changed, 42 insertions(+), 29 deletions(-) rename test/rules/no-this-reassignment/{allow-this-destructuring => allow-destructuring}/test.ts.lint (80%) rename test/rules/no-this-reassignment/{allow-this-destructuring => allow-destructuring}/tslint.json (62%) rename test/rules/no-this-reassignment/{allowed-this-names => allowed-names}/test.ts.lint (100%) rename test/rules/no-this-reassignment/{allowed-this-names => allowed-names}/tslint.json (62%) diff --git a/src/configs/latest.ts b/src/configs/latest.ts index 52e3c35dc2b..6b7da38e3d3 100644 --- a/src/configs/latest.ts +++ b/src/configs/latest.ts @@ -41,6 +41,7 @@ export const rules = { true, "check-parameters", ], + "no-this-reassignment": true, }; // tslint:enable object-literal-sort-keys diff --git a/src/rules/noThisReassignmentRule.ts b/src/rules/noThisReassignmentRule.ts index c66eaab3369..4476758263c 100644 --- a/src/rules/noThisReassignmentRule.ts +++ b/src/rules/noThisReassignmentRule.ts @@ -20,17 +20,32 @@ import * as ts from "typescript"; import * as Lint from "../index"; -const ALLOW_THIS_DESTRUCTURING = "allow-this-destructuring"; -const ALLOWED_THIS_NAMES = "allowed-this-names"; +const ALLOW_THIS_DESTRUCTURING = "allow-destructuring"; +const ALLOWED_THIS_NAMES = "allowed-names"; interface Options { - allowedThisNames: string[]; - allowThisDestructuring: boolean; + allowedNames: string[]; + allowDestructuring: boolean; } -type RuleArgument = boolean | { - "allow-this-destructuring"?: boolean; - "allowed-this-names"?: string[]; +interface ConfigOptions { + "allow-destructuring"?: boolean; + "allowed-names"?: string[]; +} + +const parseConfigOptions = (configOptions: ConfigOptions | undefined): Options => { + const allowedNames: string[] = []; + let allowDestructuring = false; + + if (configOptions !== undefined) { + allowDestructuring = !!configOptions[ALLOW_THIS_DESTRUCTURING]; + + if (configOptions[ALLOWED_THIS_NAMES] !== undefined) { + allowedNames.push(...configOptions[ALLOWED_THIS_NAMES]!); + } + } + + return { allowedNames, allowDestructuring }; }; export class Rule extends Lint.Rules.AbstractRule { @@ -41,7 +56,7 @@ export class Rule extends Lint.Rules.AbstractRule { [ true, { - [ALLOWED_THIS_NAMES]: ["self"], + [ALLOWED_THIS_NAMES]: ["^self$"], [ALLOW_THIS_DESTRUCTURING]: true, }, ], @@ -71,27 +86,14 @@ export class Rule extends Lint.Rules.AbstractRule { typescriptOnly: false, }; - public static readonly FAILURE_STRING_BINDINGS = "Don't reassign members of `this` to local variables."; + public static FAILURE_STRING_BINDINGS = "Don't assign members of `this` to local variables."; public static FAILURE_STRING_FACTORY_IDENTIFIERS(name: string) { return `Assigning \`this\` reference to local variable not allowed: ${name}.`; } public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const allowedThisNames: string[] = []; - let allowThisDestructuring = false; - - for (const ruleArgument of this.ruleArguments as RuleArgument[]) { - if (typeof ruleArgument === "object") { - allowThisDestructuring = !!ruleArgument[ALLOW_THIS_DESTRUCTURING]; - - if (ruleArgument[ALLOWED_THIS_NAMES] !== undefined) { - allowedThisNames.push(...ruleArgument[ALLOWED_THIS_NAMES]!); - } - } - } - - const options = { allowedThisNames, allowThisDestructuring }; + const options = parseConfigOptions((this.ruleArguments as [ConfigOptions])[0]); const noThisReassignmentWalker = new NoThisReassignmentWalker(sourceFile, this.ruleName, options); return this.applyWithWalker(noThisReassignmentWalker); @@ -99,7 +101,7 @@ export class Rule extends Lint.Rules.AbstractRule { } class NoThisReassignmentWalker extends Lint.AbstractWalker { - private readonly allowedThisNameTesters = this.options.allowedThisNames.map( + private readonly allowedThisNameTesters = this.options.allowedNames.map( (allowedThisName) => new RegExp(allowedThisName)); public walk(sourceFile: ts.SourceFile): void { @@ -126,8 +128,8 @@ class NoThisReassignmentWalker extends Lint.AbstractWalker { } break; - case ts.SyntaxKind.ObjectBindingPattern: - if (!this.options.allowThisDestructuring) { + default: + if (!this.options.allowDestructuring) { this.addFailureAtNode(node, Rule.FAILURE_STRING_BINDINGS); } } diff --git a/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint b/test/rules/no-this-reassignment/allow-destructuring/test.ts.lint similarity index 80% rename from test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint rename to test/rules/no-this-reassignment/allow-destructuring/test.ts.lint index 7a13bab49be..3be40991478 100644 --- a/test/rules/no-this-reassignment/allow-this-destructuring/test.ts.lint +++ b/test/rules/no-this-reassignment/allow-destructuring/test.ts.lint @@ -2,6 +2,10 @@ const { length } = this; const { length, toString } = this; +const [foo] = this; + +const [foo, bar] = this; + const self = this; ~~~~~~~~~~~ [name % ('self')] diff --git a/test/rules/no-this-reassignment/allow-this-destructuring/tslint.json b/test/rules/no-this-reassignment/allow-destructuring/tslint.json similarity index 62% rename from test/rules/no-this-reassignment/allow-this-destructuring/tslint.json rename to test/rules/no-this-reassignment/allow-destructuring/tslint.json index 06c9eb5424e..c04cc5f9360 100644 --- a/test/rules/no-this-reassignment/allow-this-destructuring/tslint.json +++ b/test/rules/no-this-reassignment/allow-destructuring/tslint.json @@ -1,7 +1,7 @@ { "rules": { "no-this-reassignment": [true, { - "allow-this-destructuring": true + "allow-destructuring": true }] } } diff --git a/test/rules/no-this-reassignment/allowed-this-names/test.ts.lint b/test/rules/no-this-reassignment/allowed-names/test.ts.lint similarity index 100% rename from test/rules/no-this-reassignment/allowed-this-names/test.ts.lint rename to test/rules/no-this-reassignment/allowed-names/test.ts.lint diff --git a/test/rules/no-this-reassignment/allowed-this-names/tslint.json b/test/rules/no-this-reassignment/allowed-names/tslint.json similarity index 62% rename from test/rules/no-this-reassignment/allowed-this-names/tslint.json rename to test/rules/no-this-reassignment/allowed-names/tslint.json index 8b9c2aa18bf..5fc8c91602b 100644 --- a/test/rules/no-this-reassignment/allowed-this-names/tslint.json +++ b/test/rules/no-this-reassignment/allowed-names/tslint.json @@ -1,7 +1,7 @@ { "rules": { "no-this-reassignment": [true, { - "allowed-this-names": ["^start"] + "allowed-names": ["^start"] }] } } diff --git a/test/rules/no-this-reassignment/default/test.ts.lint b/test/rules/no-this-reassignment/default/test.ts.lint index 3af626180d0..94a9141c709 100644 --- a/test/rules/no-this-reassignment/default/test.ts.lint +++ b/test/rules/no-this-reassignment/default/test.ts.lint @@ -33,8 +33,14 @@ class TestClass { const { act, constructor } = this; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ [binding] + + const [foo] = this; + ~~~~~~~~~~~~ [binding] + + const [foo, bar] = this; + ~~~~~~~~~~~~~~~~~ [binding] } } -[binding]: Don't reassign members of `this` to local variables. +[binding]: Don't assign members of `this` to local variables. [identifier]: Assigning `this` reference to local variable not allowed: %s. From 507a32c8b5c9698f9dcbbce5834e975fcc6697c2 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 18 Jun 2017 15:49:32 -0700 Subject: [PATCH 8/8] Renamed to no-this-assignment (no re) --- src/configs/all.ts | 2 +- src/configs/latest.ts | 2 +- ...{noThisReassignmentRule.ts => noThisAssignmentRule.ts} | 8 ++++---- .../allow-destructuring/test.ts.lint | 0 .../allow-destructuring/tslint.json | 2 +- .../allowed-names/test.ts.lint | 0 .../allowed-names/tslint.json | 2 +- .../default/test.ts.lint | 0 test/rules/no-this-assignment/default/tslint.json | 5 +++++ test/rules/no-this-reassignment/default/tslint.json | 5 ----- 10 files changed, 13 insertions(+), 13 deletions(-) rename src/rules/{noThisReassignmentRule.ts => noThisAssignmentRule.ts} (94%) rename test/rules/{no-this-reassignment => no-this-assignment}/allow-destructuring/test.ts.lint (100%) rename test/rules/{no-this-reassignment => no-this-assignment}/allow-destructuring/tslint.json (62%) rename test/rules/{no-this-reassignment => no-this-assignment}/allowed-names/test.ts.lint (100%) rename test/rules/{no-this-reassignment => no-this-assignment}/allowed-names/tslint.json (62%) rename test/rules/{no-this-reassignment => no-this-assignment}/default/test.ts.lint (100%) create mode 100644 test/rules/no-this-assignment/default/tslint.json delete mode 100644 test/rules/no-this-reassignment/default/tslint.json diff --git a/src/configs/all.ts b/src/configs/all.ts index bc3d2cf99b4..415fe430547 100644 --- a/src/configs/all.ts +++ b/src/configs/all.ts @@ -51,7 +51,7 @@ export const rules = { "no-namespace": true, "no-non-null-assertion": true, "no-reference": true, - "no-this-reassignment": true, + "no-this-assignment": true, "no-var-requires": true, "only-arrow-functions": true, "prefer-for-of": true, diff --git a/src/configs/latest.ts b/src/configs/latest.ts index 6b7da38e3d3..cae2c38f598 100644 --- a/src/configs/latest.ts +++ b/src/configs/latest.ts @@ -41,7 +41,7 @@ export const rules = { true, "check-parameters", ], - "no-this-reassignment": true, + "no-this-assignment": true, }; // tslint:enable object-literal-sort-keys diff --git a/src/rules/noThisReassignmentRule.ts b/src/rules/noThisAssignmentRule.ts similarity index 94% rename from src/rules/noThisReassignmentRule.ts rename to src/rules/noThisAssignmentRule.ts index 4476758263c..0ca388c0bf4 100644 --- a/src/rules/noThisReassignmentRule.ts +++ b/src/rules/noThisAssignmentRule.ts @@ -81,7 +81,7 @@ export class Rule extends Lint.Rules.AbstractRule { * \`${ALLOWED_THIS_NAMES}\` may be specified as a list of regular expressions to match allowed variable names.`, rationale: "Assigning a variable to `this` instead of properly using arrow lambdas" + "may be a symptom of pre-ES6 practices or not manging scope well.", - ruleName: "no-this-reassignment", + ruleName: "no-this-assignment", type: "functionality", typescriptOnly: false, }; @@ -94,13 +94,13 @@ export class Rule extends Lint.Rules.AbstractRule { public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const options = parseConfigOptions((this.ruleArguments as [ConfigOptions])[0]); - const noThisReassignmentWalker = new NoThisReassignmentWalker(sourceFile, this.ruleName, options); + const noThisAssignmentWalker = new NoThisAssignmentWalker(sourceFile, this.ruleName, options); - return this.applyWithWalker(noThisReassignmentWalker); + return this.applyWithWalker(noThisAssignmentWalker); } } -class NoThisReassignmentWalker extends Lint.AbstractWalker { +class NoThisAssignmentWalker extends Lint.AbstractWalker { private readonly allowedThisNameTesters = this.options.allowedNames.map( (allowedThisName) => new RegExp(allowedThisName)); diff --git a/test/rules/no-this-reassignment/allow-destructuring/test.ts.lint b/test/rules/no-this-assignment/allow-destructuring/test.ts.lint similarity index 100% rename from test/rules/no-this-reassignment/allow-destructuring/test.ts.lint rename to test/rules/no-this-assignment/allow-destructuring/test.ts.lint diff --git a/test/rules/no-this-reassignment/allow-destructuring/tslint.json b/test/rules/no-this-assignment/allow-destructuring/tslint.json similarity index 62% rename from test/rules/no-this-reassignment/allow-destructuring/tslint.json rename to test/rules/no-this-assignment/allow-destructuring/tslint.json index c04cc5f9360..ba6ce5a4fd2 100644 --- a/test/rules/no-this-reassignment/allow-destructuring/tslint.json +++ b/test/rules/no-this-assignment/allow-destructuring/tslint.json @@ -1,6 +1,6 @@ { "rules": { - "no-this-reassignment": [true, { + "no-this-assignment": [true, { "allow-destructuring": true }] } diff --git a/test/rules/no-this-reassignment/allowed-names/test.ts.lint b/test/rules/no-this-assignment/allowed-names/test.ts.lint similarity index 100% rename from test/rules/no-this-reassignment/allowed-names/test.ts.lint rename to test/rules/no-this-assignment/allowed-names/test.ts.lint diff --git a/test/rules/no-this-reassignment/allowed-names/tslint.json b/test/rules/no-this-assignment/allowed-names/tslint.json similarity index 62% rename from test/rules/no-this-reassignment/allowed-names/tslint.json rename to test/rules/no-this-assignment/allowed-names/tslint.json index 5fc8c91602b..8435d774dc5 100644 --- a/test/rules/no-this-reassignment/allowed-names/tslint.json +++ b/test/rules/no-this-assignment/allowed-names/tslint.json @@ -1,6 +1,6 @@ { "rules": { - "no-this-reassignment": [true, { + "no-this-assignment": [true, { "allowed-names": ["^start"] }] } diff --git a/test/rules/no-this-reassignment/default/test.ts.lint b/test/rules/no-this-assignment/default/test.ts.lint similarity index 100% rename from test/rules/no-this-reassignment/default/test.ts.lint rename to test/rules/no-this-assignment/default/test.ts.lint diff --git a/test/rules/no-this-assignment/default/tslint.json b/test/rules/no-this-assignment/default/tslint.json new file mode 100644 index 00000000000..3fb515282cd --- /dev/null +++ b/test/rules/no-this-assignment/default/tslint.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-this-assignment": true + } +} diff --git a/test/rules/no-this-reassignment/default/tslint.json b/test/rules/no-this-reassignment/default/tslint.json deleted file mode 100644 index 86df1b9b6a8..00000000000 --- a/test/rules/no-this-reassignment/default/tslint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "no-this-reassignment": true - } -}