From e1cb0c44e67eafe232410ccba3fd6fcc9e95248d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1nchez?= Date: Sun, 6 Oct 2019 09:30:42 -0600 Subject: [PATCH] implement no-shadowed-variable converter --- src/rules/converters.ts | 3 +- src/rules/converters/no-shadowed-variable.ts | 49 +++++++++++ .../tests/no-shadowed-variable.test.ts | 85 +++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/rules/converters/no-shadowed-variable.ts create mode 100644 src/rules/converters/tests/no-shadowed-variable.test.ts diff --git a/src/rules/converters.ts b/src/rules/converters.ts index 78b2b9e94..47ceeab82 100644 --- a/src/rules/converters.ts +++ b/src/rules/converters.ts @@ -69,6 +69,7 @@ import { convertNoReference } from "./converters/no-reference"; import { convertNoRegexSpaces } from "./converters/no-regex-spaces"; import { convertNoRequireImports } from "./converters/no-require-imports"; import { convertNoReturnAwait } from "./converters/no-return-await"; +import { convertNoShadowedVariable } from "./converters/no-shadowed-variable"; import { convertNoSparseArrays } from "./converters/no-sparse-arrays"; import { convertNoStringLiteral } from "./converters/no-string-literal"; import { convertNoStringThrow } from "./converters/no-string-throw"; @@ -186,6 +187,7 @@ export const converters = new Map([ ["no-regex-spaces", convertNoRegexSpaces], ["no-require-imports", convertNoRequireImports], ["no-return-await", convertNoReturnAwait], + ["no-shadowed-variable", convertNoShadowedVariable], ["no-sparse-arrays", convertNoSparseArrays], ["no-string-literal", convertNoStringLiteral], ["no-string-throw", convertNoStringThrow], @@ -237,7 +239,6 @@ export const converters = new Map([ // ["ban", convertBan], // no-restricted-properties // ["import-blacklist", convertImportBlacklist], // no-restricted-imports // ["no-duplicate-variable", convertNoDuplicateVariable], // no-redeclare - // ["no-shadowed-variable", convertNoShadowedVariable], // no-shadow // ["no-unused-expression", convertNoUnusedExpression], // no-unused-expressions // ["space-within-parens", convertSpaceWithinParens], // space-in-parens // ["variable-name", convertVariableName], // a bunch of rules... diff --git a/src/rules/converters/no-shadowed-variable.ts b/src/rules/converters/no-shadowed-variable.ts new file mode 100644 index 000000000..b6722f2fc --- /dev/null +++ b/src/rules/converters/no-shadowed-variable.ts @@ -0,0 +1,49 @@ +import { RuleConverter } from "../converter"; + +const SELECTIVE_DISABLE_NOTICE = + "ESLint does not support selectively disabling shadowed declaration checks " + + "depending on the type of declaration, so all kinds of declarations are checked."; + +const UNDERSCORE_DISABLE_NOTICE = + "ESLint does not support disabling shadowed variable checks based on " + + "whether their names start with underscore or not, please use 'allow' in eslint configuration to " + + "provide specific variable names you want to disable the rule for."; + +export const convertNoShadowedVariable: RuleConverter = tslintRule => { + const ruleArguments: { hoist: "all" | "never" }[] = []; + const notices: string[] = []; + + if (tslintRule.ruleArguments.length === 0 || !(tslintRule.ruleArguments[0] instanceof Object)) { + ruleArguments.push({ hoist: "all" }); + } else { + const config: Record = tslintRule.ruleArguments[0]; + + if (config.underscore === false) { + notices.push(UNDERSCORE_DISABLE_NOTICE); + } + + if (config.temporalDeadZone === false) { + ruleArguments.push({ hoist: "never" }); + } else { + ruleArguments.push({ hoist: "all" }); + } + + const hasUnsupportedDisables = Object.entries(config).some( + ([key, value]) => value === false && key !== "underscore" && key !== "temporalDeadZone", + ); + + if (hasUnsupportedDisables) { + notices.push(SELECTIVE_DISABLE_NOTICE); + } + } + + return { + rules: [ + { + ...(notices.length > 0 && { notices }), + ...(ruleArguments.length > 0 && { ruleArguments }), + ruleName: "no-shadow", + }, + ], + }; +}; diff --git a/src/rules/converters/tests/no-shadowed-variable.test.ts b/src/rules/converters/tests/no-shadowed-variable.test.ts new file mode 100644 index 000000000..6a1f676dd --- /dev/null +++ b/src/rules/converters/tests/no-shadowed-variable.test.ts @@ -0,0 +1,85 @@ +import { convertNoShadowedVariable } from "../no-shadowed-variable"; + +describe(convertNoShadowedVariable, () => { + test("conversion without parameter", () => { + const result = convertNoShadowedVariable({ + ruleArguments: [], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [{ hoist: "all" }], + ruleName: "no-shadow", + }, + ], + }); + }); + + test("conversion with non-object parameter", () => { + const result = convertNoShadowedVariable({ + ruleArguments: ["will-be-ignored"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [{ hoist: "all" }], + ruleName: "no-shadow", + }, + ], + }); + }); + + test("conversion with empty parameter object", () => { + const result = convertNoShadowedVariable({ + ruleArguments: [{}], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [{ hoist: "all" }], + ruleName: "no-shadow", + }, + ], + }); + }); + + test("conversion with disabled 'temporalDeadZone'", () => { + const result = convertNoShadowedVariable({ + ruleArguments: [{ temporalDeadZone: false }], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [{ hoist: "never" }], + ruleName: "no-shadow", + }, + ], + }); + }); + + test("conversion with disabled declaration types", () => { + const result = convertNoShadowedVariable({ + ruleArguments: [{ class: false, underscore: false }], + }); + + expect(result).toEqual({ + rules: [ + { + notices: [ + "ESLint does not support disabling shadowed variable checks based on " + + "whether their names start with underscore or not, please use 'allow' in eslint configuration to " + + "provide specific variable names you want to disable the rule for.", + "ESLint does not support selectively disabling shadowed declaration checks " + + "depending on the type of declaration, so all kinds of declarations are checked.", + ], + ruleArguments: [{ hoist: "all" }], + ruleName: "no-shadow", + }, + ], + }); + }); +});