diff --git a/src/rules/converters.ts b/src/rules/converters.ts index 78b2b9e94..8d1343148 100644 --- a/src/rules/converters.ts +++ b/src/rules/converters.ts @@ -99,6 +99,7 @@ import { convertPreferTemplate } from "./converters/prefer-template"; import { convertPromiseFunctionAsync } from "./converters/promise-function-async"; import { convertRadix } from "./converters/radix"; import { convertRestrictPlusOperands } from "./converters/restrict-plus-operands"; +import { convertSemicolon } from "./converters/semicolon"; import { convertSpaceBeforeFunctionParen } from "./converters/space-before-function-paren"; import { convertSwitchDefault } from "./converters/switch-default"; import { convertTypedefWhitespace } from "./converters/typedef-whitespace"; @@ -217,6 +218,7 @@ export const converters = new Map([ ["quotemark", convertQuotemark], ["radix", convertRadix], ["restrict-plus-operands", convertRestrictPlusOperands], + ["semicolon", convertSemicolon], ["space-before-function-paren", convertSpaceBeforeFunctionParen], ["switch-default", convertSwitchDefault], ["triple-equals", convertTripleEquals], diff --git a/src/rules/converters/semicolon.ts b/src/rules/converters/semicolon.ts new file mode 100644 index 000000000..e32d94898 --- /dev/null +++ b/src/rules/converters/semicolon.ts @@ -0,0 +1,48 @@ +import { RuleConverter } from "../converter"; + +export const convertSemicolon: RuleConverter = tslintRule => { + const getMultilineDelimiter = (strategy: "always" | "never") => { + if (strategy === "always") { + return "semi"; + } + return "none"; + }; + + const ignoreInterfaces = tslintRule.ruleArguments.includes("ignore-interfaces"); + const strictBoundClassMethods = tslintRule.ruleArguments.includes("strict-bound-class-methods"); + + return { + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: [tslintRule.ruleArguments[0]], + }, + ...(ignoreInterfaces + ? [] + : [ + { + ruleName: "@typescript-eslint/member-delimiter-style", + ruleArguments: [ + "error", + { + multiline: { + delimiter: getMultilineDelimiter(tslintRule.ruleArguments[0]), + requireLast: true, + }, + singleline: { + delimiter: "semi", + requireLast: false, + }, + }, + ], + }, + ]), + ], + + notices: strictBoundClassMethods + ? [ + "Option `strict-bound-class-methods` was found, there is no exact equivalent yet supported.", + ] + : undefined, + }; +}; diff --git a/src/rules/converters/tests/semicolon.test.ts b/src/rules/converters/tests/semicolon.test.ts new file mode 100644 index 000000000..95b8d8f50 --- /dev/null +++ b/src/rules/converters/tests/semicolon.test.ts @@ -0,0 +1,199 @@ +import { convertSemicolon } from "../semicolon"; + +describe(convertSemicolon, () => { + test("conversion with always", () => { + const result = convertSemicolon({ + ruleArguments: ["always"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["always"], + }, + { + ruleName: "@typescript-eslint/member-delimiter-style", + ruleArguments: [ + "error", + { + multiline: { + delimiter: "semi", + requireLast: true, + }, + singleline: { + delimiter: "semi", + requireLast: false, + }, + }, + ], + }, + ], + }); + }); + + test("conversion with never", () => { + const result = convertSemicolon({ + ruleArguments: ["never"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["never"], + }, + { + ruleName: "@typescript-eslint/member-delimiter-style", + ruleArguments: [ + "error", + { + multiline: { + delimiter: "none", + requireLast: true, + }, + singleline: { + delimiter: "semi", + requireLast: false, + }, + }, + ], + }, + ], + }); + }); + + test("conversion with always and strict bound class methods", () => { + const result = convertSemicolon({ + ruleArguments: ["always", "strict-bound-class-methods"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["always"], + }, + { + ruleName: "@typescript-eslint/member-delimiter-style", + ruleArguments: [ + "error", + { + multiline: { + delimiter: "semi", + requireLast: true, + }, + singleline: { + delimiter: "semi", + requireLast: false, + }, + }, + ], + }, + ], + notices: [ + "Option `strict-bound-class-methods` was found, there is no exact equivalent yet supported.", + ], + }); + }); + + test("conversion with never and strict bound class methods", () => { + const result = convertSemicolon({ + ruleArguments: ["never", "strict-bound-class-methods"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["never"], + }, + { + ruleName: "@typescript-eslint/member-delimiter-style", + ruleArguments: [ + "error", + { + multiline: { + delimiter: "none", + requireLast: true, + }, + singleline: { + delimiter: "semi", + requireLast: false, + }, + }, + ], + }, + ], + notices: [ + "Option `strict-bound-class-methods` was found, there is no exact equivalent yet supported.", + ], + }); + }); + + test("conversion with always and ignore interfaces", () => { + const result = convertSemicolon({ + ruleArguments: ["always", "ignore-interfaces"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["always"], + }, + ], + }); + }); + + test("conversion with never and ignore interfaces", () => { + const result = convertSemicolon({ + ruleArguments: ["never", "ignore-interfaces"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["never"], + }, + ], + }); + }); + + test("conversion with always, strict bound class methods and ignore interfaces", () => { + const result = convertSemicolon({ + ruleArguments: ["always", "ignore-interfaces", "strict-bound-class-methods"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["always"], + }, + ], + notices: [ + "Option `strict-bound-class-methods` was found, there is no exact equivalent yet supported.", + ], + }); + }); + + test("conversion with always, strict bound class methods and ignore interfaces", () => { + const result = convertSemicolon({ + ruleArguments: ["never", "ignore-interfaces", "strict-bound-class-methods"], + }); + + expect(result).toEqual({ + rules: [ + { + ruleName: "@typescript-eslint/semi", + ruleArguments: ["never"], + }, + ], + notices: [ + "Option `strict-bound-class-methods` was found, there is no exact equivalent yet supported.", + ], + }); + }); +});