From 76303d8167cac2756f27cfeca3d24e47e76d9600 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Mon, 21 Feb 2022 22:43:59 -0800 Subject: [PATCH 1/5] feat: Add converter for `typedef` rule (#937) --- .../lintConfigs/rules/ruleConverters.ts | 2 + .../ruleConverters/tests/typedef.test.ts | 42 +++++++++++++++ .../rules/ruleConverters/typedef.ts | 53 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts create mode 100644 src/converters/lintConfigs/rules/ruleConverters/typedef.ts diff --git a/src/converters/lintConfigs/rules/ruleConverters.ts b/src/converters/lintConfigs/rules/ruleConverters.ts index e83453f2..51c9a34c 100644 --- a/src/converters/lintConfigs/rules/ruleConverters.ts +++ b/src/converters/lintConfigs/rules/ruleConverters.ts @@ -321,6 +321,7 @@ import { convertTemplateUseTrackByFunction } from "./ruleConverters/template-use import { convertTrailingComma } from "./ruleConverters/trailing-comma"; import { convertTripleEquals } from "./ruleConverters/triple-equals"; import { convertTypeLiteralDelimiter } from "./ruleConverters/type-literal-delimiter"; +import { convertTypedef } from "./ruleConverters/typedef"; import { convertTypedefWhitespace } from "./ruleConverters/typedef-whitespace"; import { convertTypeofCompare } from "./ruleConverters/typeof-compare"; import { convertUnderscoreConsistentInvocation } from "./ruleConverters/underscore-consistent-invocation"; @@ -669,6 +670,7 @@ export const ruleConverters = new Map([ ["trailing-comma", convertTrailingComma], ["triple-equals", convertTripleEquals], ["type-literal-delimiter", convertTypeLiteralDelimiter], + ["typedef", convertTypedef], ["typedef-whitespace", convertTypedefWhitespace], ["typeof-compare", convertTypeofCompare], ["underscore-consistent-invocation", convertUnderscoreConsistentInvocation], diff --git a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts new file mode 100644 index 00000000..bfdbb628 --- /dev/null +++ b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts @@ -0,0 +1,42 @@ +import { convertTypedef } from "../typedef"; + +describe(convertTypedef, () => { + test("conversion without arguments", () => { + const result = convertTypedef({ + ruleArguments: [], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/typedef", + }, + ], + }); + }); + + test("conversion with an argument", () => { + const result = convertTypedef({ + ruleArguments: [ + "parameter", + "variable-declaration-ignore-function", + "array-destructuring", + ], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [ + { + parameter: true, + variableDeclarationIgnoreFunction: true, + arrayDestructuring: true, + }, + ], + ruleName: "@typescript-eslint/typedef", + }, + ], + }); + }); +}); diff --git a/src/converters/lintConfigs/rules/ruleConverters/typedef.ts b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts new file mode 100644 index 00000000..1899f264 --- /dev/null +++ b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts @@ -0,0 +1,53 @@ +import { RuleConverter } from "../ruleConverter"; + +export const convertTypedef: RuleConverter = (tslintRule) => { + const typedefRule: Record = {}; + + if (tslintRule.ruleArguments.includes("parameter")) { + typedefRule.parameter = true; + } + + if (tslintRule.ruleArguments.includes("arrow-parameter")) { + typedefRule.arrowParameter = true; + } + + if (tslintRule.ruleArguments.includes("property-declaration")) { + typedefRule.propertyDeclaration = true; + } + + if (tslintRule.ruleArguments.includes("variable-declaration")) { + typedefRule.variableDeclaration = true; + } + + if (tslintRule.ruleArguments.includes("variable-declaration-ignore-function")) { + typedefRule.variableDeclarationIgnoreFunction = true; + } + + if (tslintRule.ruleArguments.includes("member-variable-declaration")) { + typedefRule.memberVariableDeclaration = true; + } + + if (tslintRule.ruleArguments.includes("object-destructuring")) { + typedefRule.objectDestructuring = true; + } + + if (tslintRule.ruleArguments.includes("array-destructuring")) { + typedefRule.arrayDestructuring = true; + } + + return { + ...(tslintRule.ruleArguments.some( + (item) => item === "call-signature" || item === "arrow-call-signature", + ) && { + notices: ["Options 'call-signature' and 'arrow-call-signature' are ignored"], + }), + rules: [ + { + ...(Object.keys(typedefRule).length !== 0 && { + ruleArguments: [typedefRule], + }), + ruleName: "@typescript-eslint/typedef", + }, + ], + }; +}; From 97b71ad2d4984dae2fe9eb811987b6d5e2481aca Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sat, 26 Feb 2022 20:10:08 -0800 Subject: [PATCH 2/5] style: Condense repetitive code This also uses `Set` to improve time complexity of searching to `O(n)` time --- .../rules/ruleConverters/typedef.ts | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/converters/lintConfigs/rules/ruleConverters/typedef.ts b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts index 1899f264..75db0259 100644 --- a/src/converters/lintConfigs/rules/ruleConverters/typedef.ts +++ b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts @@ -2,37 +2,21 @@ import { RuleConverter } from "../ruleConverter"; export const convertTypedef: RuleConverter = (tslintRule) => { const typedefRule: Record = {}; + const originalArguments = new Set(tslintRule.ruleArguments); + + const argumentEquivalents = { + parameter: "parameter", + "arrow-parameter": "arrowParameter", + "property-declaration": "propertyDeclaration", + "variable-declaration": "variableDeclaration", + "variable-declaration-ignore-function": "variableDeclarationIgnoreFunction", + "member-variable-declaration": "memberVariableDeclaration", + "object-destructuring": "objectDestructuring", + "array-destructuring": "arrayDestructuring", + }; - if (tslintRule.ruleArguments.includes("parameter")) { - typedefRule.parameter = true; - } - - if (tslintRule.ruleArguments.includes("arrow-parameter")) { - typedefRule.arrowParameter = true; - } - - if (tslintRule.ruleArguments.includes("property-declaration")) { - typedefRule.propertyDeclaration = true; - } - - if (tslintRule.ruleArguments.includes("variable-declaration")) { - typedefRule.variableDeclaration = true; - } - - if (tslintRule.ruleArguments.includes("variable-declaration-ignore-function")) { - typedefRule.variableDeclarationIgnoreFunction = true; - } - - if (tslintRule.ruleArguments.includes("member-variable-declaration")) { - typedefRule.memberVariableDeclaration = true; - } - - if (tslintRule.ruleArguments.includes("object-destructuring")) { - typedefRule.objectDestructuring = true; - } - - if (tslintRule.ruleArguments.includes("array-destructuring")) { - typedefRule.arrayDestructuring = true; + for (const [tslintArgument, eslintArgument] of Object.entries(argumentEquivalents)) { + if (originalArguments.has(tslintArgument)) typedefRule[eslintArgument] = true; } return { From 82fc246cf3d2b272e8a602b277043c43761e519d Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sat, 26 Feb 2022 20:17:18 -0800 Subject: [PATCH 3/5] test: Fix to use `@jest/globals` --- .../lintConfigs/rules/ruleConverters/tests/typedef.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts index bfdbb628..1abc029f 100644 --- a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts +++ b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts @@ -1,6 +1,8 @@ +import { describe, expect, test } from "@jest/globals"; + import { convertTypedef } from "../typedef"; -describe(convertTypedef, () => { +describe("convertTypedef", () => { test("conversion without arguments", () => { const result = convertTypedef({ ruleArguments: [], From 38fc3a2aa63183a19c03a3d43ed5239bbf8605fb Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sat, 26 Feb 2022 20:28:42 -0800 Subject: [PATCH 4/5] test: Add case for all argument conversions --- .../ruleConverters/tests/typedef.test.ts | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts index 1abc029f..c862c98a 100644 --- a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts +++ b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts @@ -17,7 +17,7 @@ describe("convertTypedef", () => { }); }); - test("conversion with an argument", () => { + test("conversion with a few arguments", () => { const result = convertTypedef({ ruleArguments: [ "parameter", @@ -41,4 +41,39 @@ describe("convertTypedef", () => { ], }); }); + + test("conversion with all arguments", () => { + const result = convertTypedef({ + ruleArguments: [ + "parameter", + "arrow-parameter", + "property-declaration", + "variable-declaration", + "variable-declaration-ignore-function", + "member-variable-declaration", + "object-destructuring", + "array-destructuring", + ], + }); + + expect(result).toEqual({ + rules: [ + { + ruleArguments: [ + { + parameter: true, + arrowParameter: true, + propertyDeclaration: true, + variableDeclaration: true, + variableDeclarationIgnoreFunction: true, + memberVariableDeclaration: true, + objectDestructuring: true, + arrayDestructuring: true, + }, + ], + ruleName: "@typescript-eslint/typedef", + }, + ], + }); + }); }); From f74623bead977a17026d52237abf815a4a3b2777 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sat, 26 Feb 2022 20:46:24 -0800 Subject: [PATCH 5/5] feat: Complete `typedef` support This adds full support to `explicit-function-return-type` and `explicit-module-boundary-type` --- .../ruleConverters/tests/typedef.test.ts | 98 +++++++++++++++++++ .../rules/ruleConverters/typedef.ts | 38 ++++++- 2 files changed, 132 insertions(+), 4 deletions(-) diff --git a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts index c862c98a..e13d9b9c 100644 --- a/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts +++ b/src/converters/lintConfigs/rules/ruleConverters/tests/typedef.test.ts @@ -13,6 +13,12 @@ describe("convertTypedef", () => { { ruleName: "@typescript-eslint/typedef", }, + { + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, ], }); }); @@ -38,6 +44,12 @@ describe("convertTypedef", () => { ], ruleName: "@typescript-eslint/typedef", }, + { + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, ], }); }); @@ -73,6 +85,92 @@ describe("convertTypedef", () => { ], ruleName: "@typescript-eslint/typedef", }, + { + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, + ], + }); + }); + + test("conversion with call-signature", () => { + const result = convertTypedef({ + ruleArguments: ["call-signature"], + }); + + expect(result).toEqual({ + notices: [ + "ESLint does not differentiate between the call signatures of arrow and non-arrow functions. Both will be checked", + ], + rules: [ + { + ruleName: "@typescript-eslint/typedef", + }, + { + ruleArguments: [ + { + allowExpressions: false, + allowTypedFunctionExpressions: false, + allowHigherOrderFunctions: false, + allowDirectConstAssertionInArrowFunctions: true, + allowConciseArrowFunctionExpressionsStartingWithVoid: true, + }, + ], + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ruleArguments: [ + { + allowArgumentsExplicitlyTypedAsAny: true, + allowDirectConstAssertionInArrowFunctions: true, + allowHigherOrderFunctions: false, + allowTypedFunctionExpressions: false, + }, + ], + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, + ], + }); + }); + + test("conversion with arrow-call-signature", () => { + const result = convertTypedef({ + ruleArguments: ["arrow-call-signature"], + }); + + expect(result).toEqual({ + notices: [ + "ESLint does not differentiate between the call signatures of arrow and non-arrow functions. Both will be checked", + ], + rules: [ + { + ruleName: "@typescript-eslint/typedef", + }, + { + ruleArguments: [ + { + allowExpressions: false, + allowTypedFunctionExpressions: false, + allowHigherOrderFunctions: false, + allowDirectConstAssertionInArrowFunctions: true, + allowConciseArrowFunctionExpressionsStartingWithVoid: true, + }, + ], + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ruleArguments: [ + { + allowArgumentsExplicitlyTypedAsAny: true, + allowDirectConstAssertionInArrowFunctions: true, + allowHigherOrderFunctions: false, + allowTypedFunctionExpressions: false, + }, + ], + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, ], }); }); diff --git a/src/converters/lintConfigs/rules/ruleConverters/typedef.ts b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts index 75db0259..b0a5cb84 100644 --- a/src/converters/lintConfigs/rules/ruleConverters/typedef.ts +++ b/src/converters/lintConfigs/rules/ruleConverters/typedef.ts @@ -2,6 +2,9 @@ import { RuleConverter } from "../ruleConverter"; export const convertTypedef: RuleConverter = (tslintRule) => { const typedefRule: Record = {}; + const functionReturnRule: Record = {}; + const moduleBoundaryRule: Record = {}; + const originalArguments = new Set(tslintRule.ruleArguments); const argumentEquivalents = { @@ -19,11 +22,26 @@ export const convertTypedef: RuleConverter = (tslintRule) => { if (originalArguments.has(tslintArgument)) typedefRule[eslintArgument] = true; } + const checksFunctionCallSignture = + originalArguments.has("arrow-call-signature") || originalArguments.has("call-signature"); + if (checksFunctionCallSignture) { + functionReturnRule.allowExpressions = false; + functionReturnRule.allowTypedFunctionExpressions = false; + functionReturnRule.allowHigherOrderFunctions = false; + functionReturnRule.allowDirectConstAssertionInArrowFunctions = true; + functionReturnRule.allowConciseArrowFunctionExpressionsStartingWithVoid = true; + + moduleBoundaryRule.allowArgumentsExplicitlyTypedAsAny = true; + moduleBoundaryRule.allowDirectConstAssertionInArrowFunctions = true; + moduleBoundaryRule.allowHigherOrderFunctions = false; + moduleBoundaryRule.allowTypedFunctionExpressions = false; + } + return { - ...(tslintRule.ruleArguments.some( - (item) => item === "call-signature" || item === "arrow-call-signature", - ) && { - notices: ["Options 'call-signature' and 'arrow-call-signature' are ignored"], + ...(checksFunctionCallSignture && { + notices: [ + "ESLint does not differentiate between the call signatures of arrow and non-arrow functions. Both will be checked", + ], }), rules: [ { @@ -32,6 +50,18 @@ export const convertTypedef: RuleConverter = (tslintRule) => { }), ruleName: "@typescript-eslint/typedef", }, + { + ...(Object.keys(functionReturnRule).length !== 0 && { + ruleArguments: [functionReturnRule], + }), + ruleName: "@typescript-eslint/explicit-function-return-type", + }, + { + ...(Object.keys(moduleBoundaryRule).length !== 0 && { + ruleArguments: [moduleBoundaryRule], + }), + ruleName: "@typescript-eslint/explicit-module-boundary-types", + }, ], }; };