From 1deac7be5baf18e581c530c3933a536243b36a63 Mon Sep 17 00:00:00 2001 From: "david.wuerfel" Date: Mon, 14 Oct 2019 00:04:15 +0200 Subject: [PATCH 01/41] feat (editor): add cli option to specify editor config path to convert (defaults to vscode) --- src/cli/runCli.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index 147891d02..f6338c102 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -24,6 +24,12 @@ export const runCli = async ( .option("--package [package]", "package configuration file to convert using") .option("--tslint [tslint]", "tslint configuration file to convert using") .option("--typescript [typescript]", "typescript configuration file to convert using") + .option( + "--editor [editor]", + "editor configuration file to convert using", + undefined, + ".vscode/settings.json", + ) .option("-V --version", "output the package version"); const parsedArgv = { From d8d92b04dccb2aa961e53123e9f17e283b786024 Mon Sep 17 00:00:00 2001 From: "david.wuerfel" Date: Mon, 14 Oct 2019 00:27:14 +0200 Subject: [PATCH 02/41] fix (editor): remove option configuration to fix default value --- src/cli/runCli.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index f6338c102..9d012f076 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -27,7 +27,6 @@ export const runCli = async ( .option( "--editor [editor]", "editor configuration file to convert using", - undefined, ".vscode/settings.json", ) .option("-V --version", "output the package version"); From 59bcca2428b3c419b5573a403f761bb7728c63fd Mon Sep 17 00:00:00 2001 From: "david.wuerfel" Date: Mon, 14 Oct 2019 00:28:01 +0200 Subject: [PATCH 03/41] feat (editor): add editor cli option to TSLintToESLintSettings --- src/types.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/types.ts b/src/types.ts index 474eb3f46..b4d7f7cc4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -23,6 +23,11 @@ export type TSLintToESLintSettings = { * Original TypeScript configuration file path, such as `tsconfig.json`. */ typescript?: string; + + /** + * Original Editor configuration file path, such as `.vscode/settings.json`. + */ + editor?: string; }; export type TSLintToESLintResult = ResultWithStatus; From d600d785240902b8e44b5a504376879cc2e6a271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 21 Oct 2019 21:25:51 +0200 Subject: [PATCH 04/41] feat(editor): conversion of multiple configs, read config and replace --- src/cli/main.ts | 19 ++++++- src/cli/runCli.ts | 37 +++++++++---- src/conversion/convertEditorConfig.ts | 79 +++++++++++++++++++++++++++ src/input/findEditorConfiguration.ts | 47 ++++++++++++++++ 4 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 src/conversion/convertEditorConfig.ts create mode 100644 src/input/findEditorConfiguration.ts diff --git a/src/cli/main.ts b/src/cli/main.ts index c6a3535f1..ea4c4a077 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -6,6 +6,10 @@ import { childProcessExec } from "../adapters/childProcessExec"; import { fsFileSystem } from "../adapters/fsFileSystem"; import { bind } from "../binding"; import { ConvertConfigDependencies, convertConfig } from "../conversion/convertConfig"; +import { + ConvertEditorConfigDependencies, + convertEditorConfig, +} from "../conversion/convertEditorConfig"; import { removeExtendsDuplicatedRules } from "../creation/simplification/removeExtendsDuplicatedRules"; import { RetrieveExtendsValuesDependencies, @@ -27,6 +31,7 @@ import { findPackagesConfiguration } from "../input/findPackagesConfiguration"; import { findESLintConfiguration } from "../input/findESLintConfiguration"; import { findTSLintConfiguration } from "../input/findTSLintConfiguration"; import { findTypeScriptConfiguration } from "../input/findTypeScriptConfiguration"; +import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { mergeLintConfigurations } from "../input/mergeLintConfigurations"; import { reportConversionResults, @@ -46,6 +51,10 @@ const findConfigurationDependencies = { exec: childProcessExec, }; +const findEditorConfigurationDependencies = { + fileSystem: fsFileSystem, +}; + const findOriginalConfigurationsDependencies: FindOriginalConfigurationsDependencies = { findESLintConfiguration: bind(findESLintConfiguration, findConfigurationDependencies), findPackagesConfiguration: bind(findPackagesConfiguration, findConfigurationDependencies), @@ -71,6 +80,11 @@ const writeConversionResultsDependencies: WriteConversionResultsDependencies = { fileSystem: fsFileSystem, }; +const convertEditorConfigDependencies: ConvertEditorConfigDependencies = { + findEditorConfiguration: bind(findEditorConfiguration, findEditorConfigurationDependencies), + fileSystem: fsFileSystem, +}; + const convertConfigDependencies: ConvertConfigDependencies = { convertRules: bind(convertRules, convertRulesDependencies), findOriginalConfigurations: bind( @@ -83,7 +97,10 @@ const convertConfigDependencies: ConvertConfigDependencies = { }; const runCliDependencies: RunCliDependencies = { - convertConfig: bind(convertConfig, convertConfigDependencies), + convertConfigs: [ + bind(convertConfig, convertConfigDependencies), + bind(convertEditorConfig, convertEditorConfigDependencies), + ], logger: processLogger, }; diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index 9d012f076..e5a5571a3 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -7,9 +7,10 @@ import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; import { convertConfig } from "../conversion/convertConfig"; import { TSLintToESLintSettings, TSLintToESLintResult, ResultStatus } from "../types"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/findEditorConfiguration.js"; export type RunCliDependencies = { - convertConfig: SansDependencies; + convertConfigs: SansDependencies[]; logger: Logger; }; @@ -27,7 +28,7 @@ export const runCli = async ( .option( "--editor [editor]", "editor configuration file to convert using", - ".vscode/settings.json", + DEFAULT_VSCODE_SETTINGS_PATH, ) .option("-V --version", "output the package version"); @@ -41,15 +42,13 @@ export const runCli = async ( return ResultStatus.Succeeded; } - let result: TSLintToESLintResult; + let result: TSLintToESLintResult = { + errors: [new Error("No configurations provided")], + status: ResultStatus.Failed, + }; - try { - result = await dependencies.convertConfig(parsedArgv); - } catch (error) { - result = { - errors: [error as Error], - status: ResultStatus.Failed, - }; + for (const convertConfig of dependencies.convertConfigs) { + result = await tryConvertConfig(convertConfig, parsedArgv); } switch (result.status) { @@ -80,3 +79,21 @@ export const runCli = async ( return result.status; }; + +const tryConvertConfig = async ( + config: SansDependencies, + argv: Partial, +): Promise => { + let result: TSLintToESLintResult; + + try { + result = await config(argv as TSLintToESLintSettings); + } catch (error) { + result = { + errors: [error as Error], + status: ResultStatus.Failed, + }; + } + + return result; +}; diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts new file mode 100644 index 000000000..3f6720964 --- /dev/null +++ b/src/conversion/convertEditorConfig.ts @@ -0,0 +1,79 @@ +import { FileSystem } from "../adapters/fileSystem"; +import { SansDependencies } from "../binding"; +import { + findEditorConfiguration, + DEFAULT_VSCODE_SETTINGS_PATH, +} from "../input/findEditorConfiguration"; +import { TSLintToESLintSettings, ResultWithStatus, ResultStatus } from "../types"; +import { formatOutput } from "../creation/formatting/formatOutput"; + +export type ConvertEditorConfigDependencies = { + findEditorConfiguration: SansDependencies; + fileSystem: Pick; +}; + +/** + * Root-level driver to convert an editor configuration. + * + * Will currently only convert the rules: + * "editor.codeActionsOnSave" -> "source.fixAll.tslint" + * into + * "eslint.autoFixOnSave" + * + * TODO: devinmotion: Replacements should be moved into rules set (by editor). + */ +export const convertEditorConfig = async ( + dependencies: ConvertEditorConfigDependencies, + settings: TSLintToESLintSettings, +): Promise => { + // 1. Existing configurations are read + const originalEditorConfiguration = await dependencies.findEditorConfiguration(settings.editor); + if (originalEditorConfiguration instanceof Error) { + return { + errors: [originalEditorConfiguration], + status: ResultStatus.Failed, + }; + } + + // TODO: devinmotion: The following logic may be moved to editor conversion rules. + // 2. Get relevant section in editor configuration + const codeActionsOnSave = originalEditorConfiguration["editor.codeActionsOnSave"]; + + // 3. Split properties to replace and original ones + const { + "source.fixAll.tslint": originalSourceFixAllTsLint, + ...codeActionsOnSaveWithoutReplacedProperties + } = codeActionsOnSave; + + // Nothing to convert + if (!originalSourceFixAllTsLint) { + return { + status: ResultStatus.Succeeded, + }; + } + + // 4. Rewrite editor configuration with replacements. + const newEditorConfiguration = { + ...originalEditorConfiguration, + "editor.codeActionsOnSave": codeActionsOnSaveWithoutReplacedProperties, + "eslint.autoFixOnSave": originalSourceFixAllTsLint, + }; + + const output = newEditorConfiguration; + const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; + + try { + await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output)); + } catch (fileWriteError) { + if (fileWriteError !== undefined) { + return { + errors: [fileWriteError], + status: ResultStatus.Failed, + }; + } + } + + return { + status: ResultStatus.Succeeded, + }; +}; diff --git a/src/input/findEditorConfiguration.ts b/src/input/findEditorConfiguration.ts new file mode 100644 index 000000000..4ffbbd293 --- /dev/null +++ b/src/input/findEditorConfiguration.ts @@ -0,0 +1,47 @@ +import { FileSystem } from "../adapters/fileSystem"; +import { DeepPartial } from "./findConfiguration"; + +/** + * TODO: devinmotion: This may be moved into a more centralized place. + */ +export const DEFAULT_VSCODE_SETTINGS_PATH = ".vscode/settings.json"; + +/** + * TODO: devinmotion: This may be moved to special config conversion rules. + */ +export type EditorConfiguration = { + "editor.codeActionsOnSave": { + "source.fixAll.tslint": boolean; + }; +}; + +export type FindEditorConfigurationDependencies = { + fileSystem: Pick; +}; + +export const findEditorConfiguration = async ( + dependencies: FindEditorConfigurationDependencies, + config: string | undefined, +): Promise | Error> => { + const rawConfiguration = await readConfiguration( + dependencies.fileSystem, + config || DEFAULT_VSCODE_SETTINGS_PATH, + ); + + return rawConfiguration; +}; + +const readConfiguration = async ( + fileSystem: Pick, + path: string, +): Promise | Error> => { + try { + const fileContents = await fileSystem.readFile(path); + if (fileContents instanceof Error) { + throw new Error(path); + } + return JSON.parse(fileContents) as DeepPartial; + } catch (error) { + return new Error(`Error parsing configuration: ${error}`); + } +}; From 7452b3dd6867192a27fb80cc15cd9a589084adcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 21 Oct 2019 21:40:44 +0200 Subject: [PATCH 05/41] test(editor): adjust tests to receive convertConfigs array --- src/cli/runCli.test.ts | 58 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/cli/runCli.test.ts b/src/cli/runCli.test.ts index 99fe90db7..c163ce6d1 100644 --- a/src/cli/runCli.test.ts +++ b/src/cli/runCli.test.ts @@ -8,9 +8,11 @@ import { runCli, RunCliDependencies } from "./runCli"; const createStubArgv = (argv: string[] = []) => ["node", "some/path/bin/file", ...argv]; const createStubRunCliDependencies = ( - overrides: Partial> = {}, + overrides: Partial> = {}, ) => ({ - convertConfig: async (): Promise => ({ status: ResultStatus.Succeeded }), + convertConfigs: [ + async (): Promise => ({ status: ResultStatus.Succeeded }), + ], logger: createStubLogger(), ...overrides, }); @@ -32,7 +34,7 @@ describe("runCli", () => { // Arrange const message = "Oh no"; const dependencies = createStubRunCliDependencies({ - convertConfig: () => Promise.reject(new Error(message)), + convertConfigs: [() => Promise.reject(new Error(message))], }); // Act @@ -49,11 +51,13 @@ describe("runCli", () => { // Arrange const complaint = "too much unit testing coverage"; const dependencies = createStubRunCliDependencies({ - convertConfig: () => - Promise.resolve({ - complaints: [complaint], - status: ResultStatus.ConfigurationError, - }), + convertConfigs: [ + () => + Promise.resolve({ + complaints: [complaint], + status: ResultStatus.ConfigurationError, + }), + ], }); // Act @@ -72,11 +76,13 @@ describe("runCli", () => { // Arrange const error = new Error("too much unit testing coverage"); const dependencies = createStubRunCliDependencies({ - convertConfig: () => - Promise.resolve({ - errors: [error], - status: ResultStatus.Failed, - }), + convertConfigs: [ + () => + Promise.resolve({ + errors: [error], + status: ResultStatus.Failed, + }), + ], }); // Act @@ -98,11 +104,13 @@ describe("runCli", () => { new Error("too much branch coverage"), ]; const dependencies = createStubRunCliDependencies({ - convertConfig: () => - Promise.resolve({ - errors, - status: ResultStatus.Failed, - }), + convertConfigs: [ + () => + Promise.resolve({ + errors, + status: ResultStatus.Failed, + }), + ], }); // Act @@ -133,12 +141,14 @@ describe("runCli", () => { it("default output should be .eslintrc.js", async () => { let defaultConfig; const dependencies = createStubRunCliDependencies({ - convertConfig: parsedArgs => { - defaultConfig = parsedArgs.config; - return Promise.resolve({ - status: ResultStatus.Succeeded, - }); - }, + convertConfigs: [ + parsedArgs => { + defaultConfig = parsedArgs.config; + return Promise.resolve({ + status: ResultStatus.Succeeded, + }); + }, + ], }); const status = await runCli(dependencies, createStubArgv()); From be3704ddf808fd2211ab3ad8e921b95a0d8af1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 21 Oct 2019 21:49:15 +0200 Subject: [PATCH 06/41] style (editor): fix incorrect import statement with js ending --- src/cli/runCli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index e5a5571a3..cfe4b870b 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -7,7 +7,7 @@ import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; import { convertConfig } from "../conversion/convertConfig"; import { TSLintToESLintSettings, TSLintToESLintResult, ResultStatus } from "../types"; -import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/findEditorConfiguration.js"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/findEditorConfiguration"; export type RunCliDependencies = { convertConfigs: SansDependencies[]; From ffb7f54554f325bf42cb86e76ed2f53448d5a47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 22 Oct 2019 20:57:04 +0200 Subject: [PATCH 07/41] fix(editor): get error return value instead of try/catch --- src/conversion/convertEditorConfig.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 3f6720964..a38ba4e3b 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -62,15 +62,15 @@ export const convertEditorConfig = async ( const output = newEditorConfiguration; const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; - try { - await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output)); - } catch (fileWriteError) { - if (fileWriteError !== undefined) { - return { - errors: [fileWriteError], - status: ResultStatus.Failed, - }; - } + const fileWriteError = await dependencies.fileSystem.writeFile( + outputPath, + formatOutput(outputPath, output), + ); + if (fileWriteError !== undefined) { + return { + errors: [fileWriteError], + status: ResultStatus.Failed, + }; } return { From da92c2be742f943969e7c119c1067157df952da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 22 Oct 2019 20:58:21 +0200 Subject: [PATCH 08/41] style: format with prettier --- src/conversion/convertEditorConfig.ts | 47 +++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index a38ba4e3b..6ab596a78 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -1,11 +1,11 @@ import { FileSystem } from "../adapters/fileSystem"; import { SansDependencies } from "../binding"; +import { formatOutput } from "../creation/formatting/formatOutput"; import { - findEditorConfiguration, DEFAULT_VSCODE_SETTINGS_PATH, + findEditorConfiguration, } from "../input/findEditorConfiguration"; -import { TSLintToESLintSettings, ResultWithStatus, ResultStatus } from "../types"; -import { formatOutput } from "../creation/formatting/formatOutput"; +import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type ConvertEditorConfigDependencies = { findEditorConfiguration: SansDependencies; @@ -45,32 +45,29 @@ export const convertEditorConfig = async ( ...codeActionsOnSaveWithoutReplacedProperties } = codeActionsOnSave; - // Nothing to convert - if (!originalSourceFixAllTsLint) { - return { - status: ResultStatus.Succeeded, + // Something to convert + if (originalSourceFixAllTsLint) { + // 4. Rewrite editor configuration with replacements. + const newEditorConfiguration = { + ...originalEditorConfiguration, + "editor.codeActionsOnSave": codeActionsOnSaveWithoutReplacedProperties, + "eslint.autoFixOnSave": originalSourceFixAllTsLint, }; - } - // 4. Rewrite editor configuration with replacements. - const newEditorConfiguration = { - ...originalEditorConfiguration, - "editor.codeActionsOnSave": codeActionsOnSaveWithoutReplacedProperties, - "eslint.autoFixOnSave": originalSourceFixAllTsLint, - }; + const output = newEditorConfiguration; + const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; - const output = newEditorConfiguration; - const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; + const fileWriteError = await dependencies.fileSystem.writeFile( + outputPath, + formatOutput(outputPath, output), + ); - const fileWriteError = await dependencies.fileSystem.writeFile( - outputPath, - formatOutput(outputPath, output), - ); - if (fileWriteError !== undefined) { - return { - errors: [fileWriteError], - status: ResultStatus.Failed, - }; + if (fileWriteError !== undefined) { + return { + errors: [fileWriteError], + status: ResultStatus.Failed, + }; + } } return { From 129de28d4309bc7dd8452881e9c57dc07af5071c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 22 Oct 2019 22:13:48 +0200 Subject: [PATCH 09/41] fix: capture every error while processing multiple configs --- src/cli/runCli.ts | 58 +++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index cfe4b870b..d49e0605b 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -1,13 +1,12 @@ import chalk from "chalk"; -import { EOL } from "os"; import { Command } from "commander"; - +import { EOL } from "os"; import { version } from "../../package.json"; import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; import { convertConfig } from "../conversion/convertConfig"; -import { TSLintToESLintSettings, TSLintToESLintResult, ResultStatus } from "../types"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/findEditorConfiguration"; +import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type RunCliDependencies = { convertConfigs: SansDependencies[]; @@ -42,15 +41,36 @@ export const runCli = async ( return ResultStatus.Succeeded; } - let result: TSLintToESLintResult = { - errors: [new Error("No configurations provided")], - status: ResultStatus.Failed, - }; - for (const convertConfig of dependencies.convertConfigs) { - result = await tryConvertConfig(convertConfig, parsedArgv); + const result = await tryConvertConfig(convertConfig, parsedArgv); + logResult(result, dependencies); + if (result.status !== ResultStatus.Succeeded) { + return result.status; + } + } + + return ResultStatus.Succeeded; +}; + +const tryConvertConfig = async ( + config: SansDependencies, + argv: Partial, +): Promise => { + let result: ResultWithStatus; + + try { + result = await config(argv as TSLintToESLintSettings); + } catch (error) { + result = { + errors: [error as Error], + status: ResultStatus.Failed, + }; } + return result; +}; + +const logResult = (result: ResultWithStatus, dependencies: RunCliDependencies) => { switch (result.status) { case ResultStatus.Succeeded: dependencies.logger.stdout.write(chalk.greenBright("✅ All is well! ✅\n")); @@ -76,24 +96,4 @@ export const runCli = async ( } break; } - - return result.status; -}; - -const tryConvertConfig = async ( - config: SansDependencies, - argv: Partial, -): Promise => { - let result: TSLintToESLintResult; - - try { - result = await config(argv as TSLintToESLintSettings); - } catch (error) { - result = { - errors: [error as Error], - status: ResultStatus.Failed, - }; - } - - return result; }; From ce993250b1c12cb2d283bd97333cf7c82919ed44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 22 Oct 2019 22:30:58 +0200 Subject: [PATCH 10/41] fix: log success only once --- src/cli/runCli.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index d49e0605b..a69d1f986 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -43,12 +43,13 @@ export const runCli = async ( for (const convertConfig of dependencies.convertConfigs) { const result = await tryConvertConfig(convertConfig, parsedArgv); - logResult(result, dependencies); if (result.status !== ResultStatus.Succeeded) { + logErrorResult(result, dependencies); return result.status; } } + dependencies.logger.stdout.write(chalk.greenBright("✅ All is well! ✅\n")); return ResultStatus.Succeeded; }; @@ -70,12 +71,8 @@ const tryConvertConfig = async ( return result; }; -const logResult = (result: ResultWithStatus, dependencies: RunCliDependencies) => { +const logErrorResult = (result: ResultWithStatus, dependencies: RunCliDependencies) => { switch (result.status) { - case ResultStatus.Succeeded: - dependencies.logger.stdout.write(chalk.greenBright("✅ All is well! ✅\n")); - break; - case ResultStatus.ConfigurationError: dependencies.logger.stderr.write(chalk.redBright("❌ ")); dependencies.logger.stderr.write(chalk.red("Could not start tslint-to-eslint:")); From 119849f31de507bfebe6c4973a3d4e11fe8d1415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 27 Oct 2019 09:30:46 +0100 Subject: [PATCH 11/41] feat(editor): add error for editor settings conversion --- src/errors/conversionError.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/errors/conversionError.ts b/src/errors/conversionError.ts index 313247a4c..3f6d54448 100644 --- a/src/errors/conversionError.ts +++ b/src/errors/conversionError.ts @@ -2,6 +2,7 @@ import { EOL } from "os"; import { TSLintRuleOptions } from "../rules/types"; import { ErrorSummary } from "./errorSummary"; +import { EditorSettingOptions } from "../settings/types"; export class ConversionError implements ErrorSummary { private constructor(private readonly summary: string) {} @@ -21,6 +22,12 @@ export class ConversionError implements ErrorSummary { ); } + public static forSettingError(error: Error, editorSetting: EditorSettingOptions) { + return new ConversionError( + `${editorSetting.settingName} threw an error during conversion: ${error.stack}${EOL}`, + ); + } + public getSummary(): string { return this.summary; } From a0b6bcd35a1517d3639525fc864ef5005f327423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 27 Oct 2019 11:00:23 +0100 Subject: [PATCH 12/41] feat(editor): make editor conversion extendable like rule conversion, no reporting --- src/cli/main.ts | 16 +++++- src/conversion/convertEditorConfig.ts | 57 ++++++------------- .../writeEditorConfigConversionResults.ts | 36 ++++++++++++ src/errors/conversionError.ts | 4 +- src/settings/convertSetting.ts | 19 +++++++ src/settings/convertSettings.ts | 53 +++++++++++++++++ src/settings/converter.ts | 34 +++++++++++ src/settings/converters.ts | 6 ++ .../converters/editor-code-actions-on-save.ts | 24 ++++++++ src/settings/types.ts | 4 ++ 10 files changed, 209 insertions(+), 44 deletions(-) create mode 100644 src/creation/writeEditorConfigConversionResults.ts create mode 100644 src/settings/convertSetting.ts create mode 100644 src/settings/convertSettings.ts create mode 100644 src/settings/converter.ts create mode 100644 src/settings/converters.ts create mode 100644 src/settings/converters/editor-code-actions-on-save.ts create mode 100644 src/settings/types.ts diff --git a/src/cli/main.ts b/src/cli/main.ts index 87002a36a..0cb56e71e 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -23,6 +23,7 @@ import { writeConversionResults, WriteConversionResultsDependencies, } from "../creation/writeConversionResults"; +import { writeConversionResults as writeEditorConfigConversionResults } from "../creation/writeEditorConfigConversionResults"; import { findOriginalConfigurations, FindOriginalConfigurationsDependencies, @@ -38,16 +39,22 @@ import { reportConversionResults, ReportConversionResultsDependencies, } from "../reporting/reportConversionResults"; -import { converters } from "../rules/converters"; +import { converters as rulesConverters } from "../rules/converters"; +import { converters as settingsConverters } from "../settings/converters"; import { convertRules } from "../rules/convertRules"; import { mergers } from "../rules/mergers"; import { runCli, RunCliDependencies } from "./runCli"; +import { convertSettings } from "../settings/convertSettings"; const convertRulesDependencies = { - converters, + converters: rulesConverters, mergers, }; +const convertSettingsDependencies = { + converters: settingsConverters, +}; + const nativeImporterDependencies: ImporterDependencies = { fileSystem: fsFileSystem, getCwd: () => process.cwd(), @@ -91,8 +98,13 @@ const writeConversionResultsDependencies: WriteConversionResultsDependencies = { }; const convertEditorConfigDependencies: ConvertEditorConfigDependencies = { + convertSettings: bind(convertSettings, convertSettingsDependencies), findEditorConfiguration: bind(findEditorConfiguration, findEditorConfigurationDependencies), fileSystem: fsFileSystem, + writeConversionResults: bind( + writeEditorConfigConversionResults, + writeConversionResultsDependencies, + ), }; const convertConfigDependencies: ConvertConfigDependencies = { diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 6ab596a78..24b76a0f7 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -1,32 +1,27 @@ import { FileSystem } from "../adapters/fileSystem"; import { SansDependencies } from "../binding"; -import { formatOutput } from "../creation/formatting/formatOutput"; import { DEFAULT_VSCODE_SETTINGS_PATH, findEditorConfiguration, } from "../input/findEditorConfiguration"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; +import { convertSettings } from "../settings/convertSettings"; +import { writeConversionResults } from "../creation/writeEditorConfigConversionResults"; export type ConvertEditorConfigDependencies = { + convertSettings: SansDependencies; findEditorConfiguration: SansDependencies; fileSystem: Pick; + writeConversionResults: SansDependencies; }; /** * Root-level driver to convert an editor configuration. - * - * Will currently only convert the rules: - * "editor.codeActionsOnSave" -> "source.fixAll.tslint" - * into - * "eslint.autoFixOnSave" - * - * TODO: devinmotion: Replacements should be moved into rules set (by editor). */ export const convertEditorConfig = async ( dependencies: ConvertEditorConfigDependencies, settings: TSLintToESLintSettings, ): Promise => { - // 1. Existing configurations are read const originalEditorConfiguration = await dependencies.findEditorConfiguration(settings.editor); if (originalEditorConfiguration instanceof Error) { return { @@ -35,41 +30,23 @@ export const convertEditorConfig = async ( }; } - // TODO: devinmotion: The following logic may be moved to editor conversion rules. - // 2. Get relevant section in editor configuration - const codeActionsOnSave = originalEditorConfiguration["editor.codeActionsOnSave"]; + const settingConversionResults = dependencies.convertSettings(originalEditorConfiguration); - // 3. Split properties to replace and original ones - const { - "source.fixAll.tslint": originalSourceFixAllTsLint, - ...codeActionsOnSaveWithoutReplacedProperties - } = codeActionsOnSave; - - // Something to convert - if (originalSourceFixAllTsLint) { - // 4. Rewrite editor configuration with replacements. - const newEditorConfiguration = { - ...originalEditorConfiguration, - "editor.codeActionsOnSave": codeActionsOnSaveWithoutReplacedProperties, - "eslint.autoFixOnSave": originalSourceFixAllTsLint, + const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; + const fileWriteError = await dependencies.writeConversionResults( + outputPath, + settingConversionResults, + originalEditorConfiguration, + ); + if (fileWriteError !== undefined) { + return { + errors: [fileWriteError], + status: ResultStatus.Failed, }; - - const output = newEditorConfiguration; - const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; - - const fileWriteError = await dependencies.fileSystem.writeFile( - outputPath, - formatOutput(outputPath, output), - ); - - if (fileWriteError !== undefined) { - return { - errors: [fileWriteError], - status: ResultStatus.Failed, - }; - } } + // TODO: devinmotion: A summary of the results may be printed to the user's console? + return { status: ResultStatus.Succeeded, }; diff --git a/src/creation/writeEditorConfigConversionResults.ts b/src/creation/writeEditorConfigConversionResults.ts new file mode 100644 index 000000000..e83034e36 --- /dev/null +++ b/src/creation/writeEditorConfigConversionResults.ts @@ -0,0 +1,36 @@ +import { FileSystem } from "../adapters/fileSystem"; +import { SettingConversionResults } from "../settings/convertSettings"; +import { formatOutput } from "./formatting/formatOutput"; +import { DeepPartial } from "../input/findConfiguration"; +import { EditorConfiguration } from "../input/findEditorConfiguration"; + +export type WriteConversionResultsDependencies = { + fileSystem: Pick; +}; + +export const writeConversionResults = async ( + dependencies: WriteConversionResultsDependencies, + outputPath: string, + conversionResults: SettingConversionResults, + originalConfiguration: DeepPartial, +) => { + const output = { + ...originalConfiguration, + ...formatConvertedSettings(conversionResults), + }; + + return await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output)); +}; + +export const formatConvertedSettings = (conversionResults: SettingConversionResults) => { + const output: { [i: string]: string | any[] } = {}; + const sortedEntries = Array.from(conversionResults.converted).sort(([nameA], [nameB]) => + nameA.localeCompare(nameB), + ); + + for (const [name, setting] of sortedEntries) { + output[name] = setting.value; + } + + return output; +}; diff --git a/src/errors/conversionError.ts b/src/errors/conversionError.ts index 3f6d54448..4716a095d 100644 --- a/src/errors/conversionError.ts +++ b/src/errors/conversionError.ts @@ -2,7 +2,7 @@ import { EOL } from "os"; import { TSLintRuleOptions } from "../rules/types"; import { ErrorSummary } from "./errorSummary"; -import { EditorSettingOptions } from "../settings/types"; +import { EditorSetting } from "../settings/types"; export class ConversionError implements ErrorSummary { private constructor(private readonly summary: string) {} @@ -22,7 +22,7 @@ export class ConversionError implements ErrorSummary { ); } - public static forSettingError(error: Error, editorSetting: EditorSettingOptions) { + public static forSettingError(error: Error, editorSetting: EditorSetting) { return new ConversionError( `${editorSetting.settingName} threw an error during conversion: ${error.stack}${EOL}`, ); diff --git a/src/settings/convertSetting.ts b/src/settings/convertSetting.ts new file mode 100644 index 000000000..4f62c6bb7 --- /dev/null +++ b/src/settings/convertSetting.ts @@ -0,0 +1,19 @@ +import { ConversionError } from "../errors/conversionError"; +import { EditorSettingConverter } from "./converter"; +import { EditorSetting } from "./types"; + +export const convertSetting = ( + editorSetting: EditorSetting, + converters: Map, +) => { + const converter = converters.get(editorSetting.settingName); + if (converter === undefined) { + return undefined; + } + + try { + return converter(editorSetting); + } catch (error) { + return ConversionError.forSettingError(error, editorSetting); + } +}; diff --git a/src/settings/convertSettings.ts b/src/settings/convertSettings.ts new file mode 100644 index 000000000..714a75400 --- /dev/null +++ b/src/settings/convertSettings.ts @@ -0,0 +1,53 @@ +import { ConversionError } from "../errors/conversionError"; +import { ErrorSummary } from "../errors/errorSummary"; +import { EditorSettingConverter } from "./converter"; +import { convertSetting } from "./convertSetting"; +import { EditorSetting } from "./types"; + +export type ConvertSettingsDependencies = { + converters: Map; +}; + +export type SettingConversionResults = { + converted: Map; + failed: ErrorSummary[]; + missing: EditorSetting[]; +}; + +export type EditorConfigurationSettings = Record; + +export const convertSettings = ( + dependencies: ConvertSettingsDependencies, + rawEditorSettings: EditorConfigurationSettings, +): SettingConversionResults => { + const converted = new Map(); + const failed: ConversionError[] = []; + const missing: EditorSetting[] = []; + + for (const [settingName, value] of Object.entries(rawEditorSettings)) { + const editorSetting = { settingName, value }; + const conversion = convertSetting(editorSetting, dependencies.converters); + + if (conversion === undefined) { + missing.push(editorSetting); + continue; + } + + if (conversion instanceof ConversionError) { + failed.push(conversion); + continue; + } + + for (const changes of conversion.settings) { + const existingConversion = converted.get(changes.settingName); + const newConversion = { ...changes }; + + if (existingConversion === undefined) { + converted.set(changes.settingName, newConversion); + continue; + } + } + } + + return { converted, failed, missing }; +}; diff --git a/src/settings/converter.ts b/src/settings/converter.ts new file mode 100644 index 000000000..a0caf0f80 --- /dev/null +++ b/src/settings/converter.ts @@ -0,0 +1,34 @@ +import { ConversionError } from "../errors/conversionError"; +import { EditorSetting } from "./types"; + +/** + * Attempts to convert a TSLint editor setting into the ESLint equivalents. + */ +export type EditorSettingConverter = ( + tslintEditorSetting: EditorSetting, +) => ConversionError | EditorSettingConversionResult; + +/** + * Successful result from converting a TSLint editor setting to its ESLint equivalents. + */ +export type EditorSettingConversionResult = { + /** + * At least one equivalent ESLint setting. + */ + settings: ConvertedEditorSettingChanges[]; +}; + +/** + * An ESLint editor setting equivalent to a previously enabled TSLint editor setting. + */ +export type ConvertedEditorSettingChanges = { + /** + * Any values for that ESLint editor setting. + */ + value: any; + + /** + * Equivalent ESLint editor setting name that should be enabled. + */ + settingName: string; +}; diff --git a/src/settings/converters.ts b/src/settings/converters.ts new file mode 100644 index 000000000..9e5cea6f2 --- /dev/null +++ b/src/settings/converters.ts @@ -0,0 +1,6 @@ +import { convertEditorCodeActionsOnSave } from "./converters/editor-code-actions-on-save"; + +/** + * Keys TSLint property names in editor settings to their ESLint editor settings converters. + */ +export const converters = new Map([["editor.codeActionsOnSave", convertEditorCodeActionsOnSave]]); diff --git a/src/settings/converters/editor-code-actions-on-save.ts b/src/settings/converters/editor-code-actions-on-save.ts new file mode 100644 index 000000000..ef0fb6351 --- /dev/null +++ b/src/settings/converters/editor-code-actions-on-save.ts @@ -0,0 +1,24 @@ +import { EditorSettingConverter } from "../converter"; + +const SUB_SETTING_SOURCE_FIXALL = "source.fixAll.tslint"; + +export const convertEditorCodeActionsOnSave: EditorSettingConverter = originalCodeActionsOnSave => { + // Split properties to replace (into parent) and original ones. + const { + [SUB_SETTING_SOURCE_FIXALL]: originalSourceFixAllTsLint, + ...codeActionsOnSaveWithoutReplacedProperties + } = originalCodeActionsOnSave.value; + + return { + settings: [ + { + settingName: "editor.codeActionsOnSave", + value: codeActionsOnSaveWithoutReplacedProperties, + }, + { + settingName: "eslint.autoFixOnSave", + value: originalSourceFixAllTsLint, + }, + ], + }; +}; diff --git a/src/settings/types.ts b/src/settings/types.ts new file mode 100644 index 000000000..50138d519 --- /dev/null +++ b/src/settings/types.ts @@ -0,0 +1,4 @@ +export type EditorSetting = { + settingName: string; + value: any; +}; From 8f409ca501142155ae58dcec6ea9ca789d5d6c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 27 Oct 2019 11:22:02 +0100 Subject: [PATCH 13/41] refactor(editor): extract vscode settings path and editor config into new type files --- src/cli/runCli.ts | 2 +- src/conversion/convertEditorConfig.ts | 10 ++++------ .../writeEditorConfigConversionResults.ts | 4 ++-- src/input/editorConfiguration.ts | 1 + src/input/findEditorConfiguration.ts | 16 ++-------------- src/input/vsCodeSettings.ts | 1 + 6 files changed, 11 insertions(+), 23 deletions(-) create mode 100644 src/input/editorConfiguration.ts create mode 100644 src/input/vsCodeSettings.ts diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index a69d1f986..12c3f9edc 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -5,7 +5,7 @@ import { version } from "../../package.json"; import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; import { convertConfig } from "../conversion/convertConfig"; -import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/findEditorConfiguration"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings.js"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type RunCliDependencies = { diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 24b76a0f7..8e75bfb8e 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -1,12 +1,10 @@ import { FileSystem } from "../adapters/fileSystem"; import { SansDependencies } from "../binding"; -import { - DEFAULT_VSCODE_SETTINGS_PATH, - findEditorConfiguration, -} from "../input/findEditorConfiguration"; -import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; -import { convertSettings } from "../settings/convertSettings"; import { writeConversionResults } from "../creation/writeEditorConfigConversionResults"; +import { findEditorConfiguration } from "../input/findEditorConfiguration"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings"; +import { convertSettings } from "../settings/convertSettings"; +import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type ConvertEditorConfigDependencies = { convertSettings: SansDependencies; diff --git a/src/creation/writeEditorConfigConversionResults.ts b/src/creation/writeEditorConfigConversionResults.ts index e83034e36..7bd4cbb71 100644 --- a/src/creation/writeEditorConfigConversionResults.ts +++ b/src/creation/writeEditorConfigConversionResults.ts @@ -1,8 +1,8 @@ import { FileSystem } from "../adapters/fileSystem"; +import { EditorConfiguration } from "../input/editorConfiguration"; +import { DeepPartial } from "../input/findConfiguration"; import { SettingConversionResults } from "../settings/convertSettings"; import { formatOutput } from "./formatting/formatOutput"; -import { DeepPartial } from "../input/findConfiguration"; -import { EditorConfiguration } from "../input/findEditorConfiguration"; export type WriteConversionResultsDependencies = { fileSystem: Pick; diff --git a/src/input/editorConfiguration.ts b/src/input/editorConfiguration.ts new file mode 100644 index 000000000..817030b42 --- /dev/null +++ b/src/input/editorConfiguration.ts @@ -0,0 +1 @@ +export type EditorConfiguration = { [key: string]: any }; diff --git a/src/input/findEditorConfiguration.ts b/src/input/findEditorConfiguration.ts index 4ffbbd293..0067e6d6f 100644 --- a/src/input/findEditorConfiguration.ts +++ b/src/input/findEditorConfiguration.ts @@ -1,19 +1,7 @@ import { FileSystem } from "../adapters/fileSystem"; +import { EditorConfiguration } from "./editorConfiguration"; import { DeepPartial } from "./findConfiguration"; - -/** - * TODO: devinmotion: This may be moved into a more centralized place. - */ -export const DEFAULT_VSCODE_SETTINGS_PATH = ".vscode/settings.json"; - -/** - * TODO: devinmotion: This may be moved to special config conversion rules. - */ -export type EditorConfiguration = { - "editor.codeActionsOnSave": { - "source.fixAll.tslint": boolean; - }; -}; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "./vsCodeSettings"; export type FindEditorConfigurationDependencies = { fileSystem: Pick; diff --git a/src/input/vsCodeSettings.ts b/src/input/vsCodeSettings.ts new file mode 100644 index 000000000..6eef5583d --- /dev/null +++ b/src/input/vsCodeSettings.ts @@ -0,0 +1 @@ +export const DEFAULT_VSCODE_SETTINGS_PATH = ".vscode/settings.json"; From 77eee95ad7a23ab5cad6174aff569d376aabfc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Fri, 1 Nov 2019 15:50:59 +0100 Subject: [PATCH 14/41] fix: remove file ending from import statement --- src/cli/runCli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index 12c3f9edc..36d140a9a 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -5,7 +5,7 @@ import { version } from "../../package.json"; import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; import { convertConfig } from "../conversion/convertConfig"; -import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings.js"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type RunCliDependencies = { From effbacc8a8c1546ef1f6f4770140d171c1fb864e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Fri, 1 Nov 2019 15:53:05 +0100 Subject: [PATCH 15/41] fix: change import of DeepPartial --- src/creation/writeEditorConfigConversionResults.ts | 2 +- src/input/findEditorConfiguration.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/creation/writeEditorConfigConversionResults.ts b/src/creation/writeEditorConfigConversionResults.ts index 7bd4cbb71..349186cc3 100644 --- a/src/creation/writeEditorConfigConversionResults.ts +++ b/src/creation/writeEditorConfigConversionResults.ts @@ -1,8 +1,8 @@ import { FileSystem } from "../adapters/fileSystem"; import { EditorConfiguration } from "../input/editorConfiguration"; -import { DeepPartial } from "../input/findConfiguration"; import { SettingConversionResults } from "../settings/convertSettings"; import { formatOutput } from "./formatting/formatOutput"; +import { DeepPartial } from "../input/findReportedConfiguration"; export type WriteConversionResultsDependencies = { fileSystem: Pick; diff --git a/src/input/findEditorConfiguration.ts b/src/input/findEditorConfiguration.ts index 0067e6d6f..6ae240171 100644 --- a/src/input/findEditorConfiguration.ts +++ b/src/input/findEditorConfiguration.ts @@ -1,7 +1,7 @@ import { FileSystem } from "../adapters/fileSystem"; import { EditorConfiguration } from "./editorConfiguration"; -import { DeepPartial } from "./findConfiguration"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "./vsCodeSettings"; +import { DeepPartial } from "./findReportedConfiguration"; export type FindEditorConfigurationDependencies = { fileSystem: Pick; From 48956eafcf56994e78c1d3ceacf36727a8313916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Fri, 1 Nov 2019 16:12:04 +0100 Subject: [PATCH 16/41] feat(editor): report converted settings --- src/cli/main.ts | 12 ++-- src/conversion/convertEditorConfig.ts | 6 +- src/reporting/dependencies.ts | 5 ++ src/reporting/reportConversionResults.ts | 7 +- .../reportSettingConversionResults.ts | 66 +++++++++++++++++++ 5 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 src/reporting/dependencies.ts create mode 100644 src/reporting/reportSettingConversionResults.ts diff --git a/src/cli/main.ts b/src/cli/main.ts index 0cb56e71e..f56aa08d9 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -35,10 +35,9 @@ import { findTypeScriptConfiguration } from "../input/findTypeScriptConfiguratio import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { importer, ImporterDependencies } from "../input/importer"; import { mergeLintConfigurations } from "../input/mergeLintConfigurations"; -import { - reportConversionResults, - ReportConversionResultsDependencies, -} from "../reporting/reportConversionResults"; +import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; +import { reportConversionResults } from "../reporting/reportConversionResults"; +import { ReportConversionResultsDependencies } from "../reporting/dependencies"; import { converters as rulesConverters } from "../rules/converters"; import { converters as settingsConverters } from "../settings/converters"; import { convertRules } from "../rules/convertRules"; @@ -100,7 +99,10 @@ const writeConversionResultsDependencies: WriteConversionResultsDependencies = { const convertEditorConfigDependencies: ConvertEditorConfigDependencies = { convertSettings: bind(convertSettings, convertSettingsDependencies), findEditorConfiguration: bind(findEditorConfiguration, findEditorConfigurationDependencies), - fileSystem: fsFileSystem, + reportConversionResults: bind( + reportSettingConversionResults, + reportConversionResultsDependencies, + ), writeConversionResults: bind( writeEditorConfigConversionResults, writeConversionResultsDependencies, diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 8e75bfb8e..1319bdac5 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -1,15 +1,15 @@ -import { FileSystem } from "../adapters/fileSystem"; import { SansDependencies } from "../binding"; import { writeConversionResults } from "../creation/writeEditorConfigConversionResults"; import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings"; import { convertSettings } from "../settings/convertSettings"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; +import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; export type ConvertEditorConfigDependencies = { convertSettings: SansDependencies; findEditorConfiguration: SansDependencies; - fileSystem: Pick; + reportConversionResults: SansDependencies; writeConversionResults: SansDependencies; }; @@ -43,7 +43,7 @@ export const convertEditorConfig = async ( }; } - // TODO: devinmotion: A summary of the results may be printed to the user's console? + dependencies.reportConversionResults(settingConversionResults); return { status: ResultStatus.Succeeded, diff --git a/src/reporting/dependencies.ts b/src/reporting/dependencies.ts new file mode 100644 index 000000000..77b3b6f1d --- /dev/null +++ b/src/reporting/dependencies.ts @@ -0,0 +1,5 @@ +import { Logger } from "../adapters/logger"; + +export type ReportConversionResultsDependencies = { + logger: Logger; +}; diff --git a/src/reporting/reportConversionResults.ts b/src/reporting/reportConversionResults.ts index 7cd25c8fd..bfc0118b1 100644 --- a/src/reporting/reportConversionResults.ts +++ b/src/reporting/reportConversionResults.ts @@ -4,11 +4,8 @@ import { EOL } from "os"; import { Logger } from "../adapters/logger"; import { ErrorSummary } from "../errors/errorSummary"; import { RuleConversionResults } from "../rules/convertRules"; -import { TSLintRuleOptions, ESLintRuleOptions } from "../rules/types"; - -export type ReportConversionResultsDependencies = { - logger: Logger; -}; +import { ESLintRuleOptions, TSLintRuleOptions } from "../rules/types"; +import { ReportConversionResultsDependencies } from "./dependencies"; export const reportConversionResults = ( dependencies: ReportConversionResultsDependencies, diff --git a/src/reporting/reportSettingConversionResults.ts b/src/reporting/reportSettingConversionResults.ts new file mode 100644 index 000000000..59e270cdd --- /dev/null +++ b/src/reporting/reportSettingConversionResults.ts @@ -0,0 +1,66 @@ +import chalk from "chalk"; +import { EOL } from "os"; + +import { Logger } from "../adapters/logger"; +import { ErrorSummary } from "../errors/errorSummary"; +import { SettingConversionResults } from "../settings/convertSettings"; +import { EditorSetting } from "../settings/types"; +import { ReportConversionResultsDependencies } from "./dependencies"; + +export const reportSettingConversionResults = ( + dependencies: ReportConversionResultsDependencies, + settingConversionResults: SettingConversionResults, +) => { + if (settingConversionResults.converted.size !== 0) { + logSuccessfulConversions(settingConversionResults.converted, dependencies.logger); + } + + if (settingConversionResults.failed.length !== 0) { + logFailedConversions(settingConversionResults.failed, dependencies.logger); + } + + if (settingConversionResults.missing.length !== 0) { + logMissingSettings(settingConversionResults.missing, dependencies.logger); + } +}; + +const logSuccessfulConversions = (converted: Map, logger: Logger) => { + logger.stdout.write(chalk.greenBright(`✨ ${converted.size}`)); + logger.stdout.write( + converted.size === 1 + ? chalk.green(" setting replaced with its ESLint equivalent.") + : chalk.green(" settings replaced with their ESLint equivalents."), + ); + logger.stdout.write(chalk.greenBright(` ✨${EOL}`)); +}; + +const logFailedConversions = (failed: ErrorSummary[], logger: Logger) => { + logger.stderr.write(`${chalk.redBright(`💀 ${failed.length}`)}`); + logger.stderr.write(chalk.red(` error${failed.length === 1 ? "" : "s"}`)); + logger.stderr.write(chalk.red(" thrown.")); + logger.stderr.write(chalk.redBright(` 💀${EOL}`)); + + logger.info.write(failed.map(failed => failed.getSummary()).join("")); + + logger.stderr.write(chalk.gray(`Check ${logger.debugFileName} for details.${EOL}`)); +}; + +const logMissingSettings = (missing: EditorSetting[], logger: Logger) => { + logger.stdout.write(chalk.yellowBright(`️👀 ${missing.length}`)); + logger.stdout.write( + chalk.yellow( + missing.length === 1 + ? " setting does not yet have an ESLint equivalent" + : " settings do not yet have ESLint equivalents", + ), + ); + logger.stdout.write(chalk.yellowBright(` 👀${EOL}`)); + + logger.info.write( + missing + .map( + ({ settingName }) => `${settingName} does not yet have an ESLint equivalent.${EOL}`, + ) + .join(""), + ); +}; From 07ad57f9b72a4c16847c76ca4b366def81cf4d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sat, 30 Nov 2019 13:12:09 +0100 Subject: [PATCH 17/41] refactor: extract general log outputs from report rules and settings convertions --- src/reporting/reportConversionResults.ts | 76 ++++--------------- src/reporting/reportOutputs.ts | 68 +++++++++++++++++ .../reportSettingConversionResults.ts | 64 +++++----------- 3 files changed, 101 insertions(+), 107 deletions(-) create mode 100644 src/reporting/reportOutputs.ts diff --git a/src/reporting/reportConversionResults.ts b/src/reporting/reportConversionResults.ts index c45ef7ab3..a89d67c6f 100644 --- a/src/reporting/reportConversionResults.ts +++ b/src/reporting/reportConversionResults.ts @@ -2,17 +2,22 @@ import chalk from "chalk"; import { EOL } from "os"; import { Logger } from "../adapters/logger"; -import { ErrorSummary } from "../errors/errorSummary"; import { RuleConversionResults } from "../rules/convertRules"; import { ESLintRuleOptions, TSLintRuleOptions } from "../rules/types"; import { ReportConversionResultsDependencies } from "./dependencies"; +import { + logFailedConversions, + logMissingConversionTarget, + logMissingPlugins, + logSuccessfulConversions, +} from "./reportOutputs"; export const reportConversionResults = ( dependencies: ReportConversionResultsDependencies, ruleConversionResults: RuleConversionResults, ) => { if (ruleConversionResults.converted.size !== 0) { - logSuccessfulConversions(ruleConversionResults.converted, dependencies.logger); + logSuccessfulConversions("rule", ruleConversionResults.converted, dependencies.logger); logNotices(ruleConversionResults.converted, dependencies.logger); } @@ -21,7 +26,14 @@ export const reportConversionResults = ( } if (ruleConversionResults.missing.length !== 0) { - logMissingRules(ruleConversionResults.missing, dependencies.logger); + const missingSettingOutputMapping = (setting: TSLintRuleOptions) => + `${setting.ruleName} does not yet have an ESLint equivalent.${EOL}`; + logMissingConversionTarget( + "rule", + missingSettingOutputMapping, + ruleConversionResults.missing, + dependencies.logger, + ); } if (ruleConversionResults.plugins.size !== 0) { @@ -29,64 +41,6 @@ export const reportConversionResults = ( } }; -const logSuccessfulConversions = (converted: Map, logger: Logger) => { - logger.stdout.write(chalk.greenBright(`✨ ${converted.size}`)); - logger.stdout.write( - converted.size === 1 - ? chalk.green(" rule replaced with its ESLint equivalent.") - : chalk.green(" rules replaced with their ESLint equivalents."), - ); - logger.stdout.write(chalk.greenBright(` ✨${EOL}`)); -}; - -const logFailedConversions = (failed: ErrorSummary[], logger: Logger) => { - logger.stderr.write(`${chalk.redBright(`💀 ${failed.length}`)}`); - logger.stderr.write(chalk.red(` error${failed.length === 1 ? "" : "s"}`)); - logger.stderr.write(chalk.red(" thrown.")); - logger.stderr.write(chalk.redBright(` 💀${EOL}`)); - - logger.info.write(failed.map(failed => failed.getSummary()).join("")); - - logger.stderr.write(chalk.gray(`Check ${logger.debugFileName} for details.${EOL}`)); -}; - -const logMissingRules = (missing: TSLintRuleOptions[], logger: Logger) => { - logger.stdout.write(chalk.yellowBright(`️👀 ${missing.length}`)); - logger.stdout.write( - chalk.yellow( - missing.length === 1 - ? " rule does not yet have an ESLint equivalent" - : " rules do not yet have ESLint equivalents", - ), - ); - logger.stdout.write( - chalk.yellow( - " (see generated log file); defaulting to eslint-plugin-tslint for these rules.", - ), - ); - logger.stdout.write(chalk.yellowBright(` 👀${EOL}`)); - - logger.info.write( - missing - .map(({ ruleName }) => `${ruleName} does not yet have an ESLint equivalent.${EOL}`) - .join(""), - ); -}; - -const logMissingPlugins = (plugins: Set, logger: Logger) => { - logger.stdout.write(chalk.cyanBright(`⚡ ${plugins.size}`)); - logger.stdout.write(chalk.cyan(" package")); - logger.stdout.write(chalk.cyan(plugins.size === 1 ? " is" : "s are")); - logger.stdout.write(chalk.cyan(` required for new ESLint rules.`)); - logger.stdout.write(chalk.cyanBright(` ⚡${EOL}`)); - - logger.stdout.write( - Array.from(plugins) - .map(pluginName => `\t${chalk.cyanBright(pluginName)}${EOL}`) - .join(""), - ); -}; - type RuleWithNotices = { notices: any[]; ruleName: string; diff --git a/src/reporting/reportOutputs.ts b/src/reporting/reportOutputs.ts new file mode 100644 index 000000000..543f9ddfc --- /dev/null +++ b/src/reporting/reportOutputs.ts @@ -0,0 +1,68 @@ +import chalk from "chalk"; +import { EOL } from "os"; + +import { Logger } from "../adapters/logger"; +import { ErrorSummary } from "../errors/errorSummary"; + +export const logSuccessfulConversions = ( + conversionTypeName: string, + converted: Map, + logger: Logger, +) => { + logger.stdout.write(chalk.greenBright(`✨ ${converted.size}`)); + logger.stdout.write( + converted.size === 1 + ? chalk.green(` ${conversionTypeName} replaced with its ESLint equivalent.`) + : chalk.green(` ${conversionTypeName}s replaced with their ESLint equivalents.`), + ); + logger.stdout.write(chalk.greenBright(` ✨${EOL}`)); +}; + +export const logFailedConversions = (failed: ErrorSummary[], logger: Logger) => { + logger.stderr.write(`${chalk.redBright(`💀 ${failed.length}`)}`); + logger.stderr.write(chalk.red(` error${failed.length === 1 ? "" : "s"}`)); + logger.stderr.write(chalk.red(" thrown.")); + logger.stderr.write(chalk.redBright(` 💀${EOL}`)); + + logger.info.write(failed.map(failed => failed.getSummary()).join("")); + + logger.stderr.write(chalk.gray(`Check ${logger.debugFileName} for details.${EOL}`)); +}; + +export const logMissingConversionTarget = ( + conversionTypeName: string, + missingOutputMapping: (missing: T) => string, + missing: T[], + logger: Logger, +) => { + logger.stdout.write(chalk.yellowBright(`️👀 ${missing.length}`)); + logger.stdout.write( + chalk.yellow( + missing.length === 1 + ? ` ${conversionTypeName} does not yet have an ESLint equivalent` + : ` ${conversionTypeName}s do not yet have ESLint equivalents`, + ), + ); + logger.stdout.write( + chalk.yellow( + ` (see generated log file); defaulting to eslint-plugin-tslint for these ${conversionTypeName}s.`, + ), + ); + logger.stdout.write(chalk.yellowBright(` 👀${EOL}`)); + + logger.info.write(missing.map(conversion => missingOutputMapping(conversion)).join("")); +}; + +export const logMissingPlugins = (plugins: Set, logger: Logger) => { + logger.stdout.write(chalk.cyanBright(`⚡ ${plugins.size}`)); + logger.stdout.write(chalk.cyan(" package")); + logger.stdout.write(chalk.cyan(plugins.size === 1 ? " is" : "s are")); + logger.stdout.write(chalk.cyan(` required for new ESLint rules.`)); + logger.stdout.write(chalk.cyanBright(` ⚡${EOL}`)); + + logger.stdout.write( + Array.from(plugins) + .map(pluginName => `\t${chalk.cyanBright(pluginName)}${EOL}`) + .join(""), + ); +}; diff --git a/src/reporting/reportSettingConversionResults.ts b/src/reporting/reportSettingConversionResults.ts index 59e270cdd..db71bf2c9 100644 --- a/src/reporting/reportSettingConversionResults.ts +++ b/src/reporting/reportSettingConversionResults.ts @@ -1,18 +1,24 @@ -import chalk from "chalk"; import { EOL } from "os"; -import { Logger } from "../adapters/logger"; -import { ErrorSummary } from "../errors/errorSummary"; import { SettingConversionResults } from "../settings/convertSettings"; import { EditorSetting } from "../settings/types"; import { ReportConversionResultsDependencies } from "./dependencies"; +import { + logFailedConversions, + logMissingConversionTarget, + logSuccessfulConversions, +} from "./reportOutputs"; export const reportSettingConversionResults = ( dependencies: ReportConversionResultsDependencies, settingConversionResults: SettingConversionResults, ) => { if (settingConversionResults.converted.size !== 0) { - logSuccessfulConversions(settingConversionResults.converted, dependencies.logger); + logSuccessfulConversions( + "setting", + settingConversionResults.converted, + dependencies.logger, + ); } if (settingConversionResults.failed.length !== 0) { @@ -20,47 +26,13 @@ export const reportSettingConversionResults = ( } if (settingConversionResults.missing.length !== 0) { - logMissingSettings(settingConversionResults.missing, dependencies.logger); + const missingSettingOutputMapping = (setting: EditorSetting) => + `${setting.settingName} does not yet have an ESLint equivalent.${EOL}`; + logMissingConversionTarget( + "setting", + missingSettingOutputMapping, + settingConversionResults.missing, + dependencies.logger, + ); } }; - -const logSuccessfulConversions = (converted: Map, logger: Logger) => { - logger.stdout.write(chalk.greenBright(`✨ ${converted.size}`)); - logger.stdout.write( - converted.size === 1 - ? chalk.green(" setting replaced with its ESLint equivalent.") - : chalk.green(" settings replaced with their ESLint equivalents."), - ); - logger.stdout.write(chalk.greenBright(` ✨${EOL}`)); -}; - -const logFailedConversions = (failed: ErrorSummary[], logger: Logger) => { - logger.stderr.write(`${chalk.redBright(`💀 ${failed.length}`)}`); - logger.stderr.write(chalk.red(` error${failed.length === 1 ? "" : "s"}`)); - logger.stderr.write(chalk.red(" thrown.")); - logger.stderr.write(chalk.redBright(` 💀${EOL}`)); - - logger.info.write(failed.map(failed => failed.getSummary()).join("")); - - logger.stderr.write(chalk.gray(`Check ${logger.debugFileName} for details.${EOL}`)); -}; - -const logMissingSettings = (missing: EditorSetting[], logger: Logger) => { - logger.stdout.write(chalk.yellowBright(`️👀 ${missing.length}`)); - logger.stdout.write( - chalk.yellow( - missing.length === 1 - ? " setting does not yet have an ESLint equivalent" - : " settings do not yet have ESLint equivalents", - ), - ); - logger.stdout.write(chalk.yellowBright(` 👀${EOL}`)); - - logger.info.write( - missing - .map( - ({ settingName }) => `${settingName} does not yet have an ESLint equivalent.${EOL}`, - ) - .join(""), - ); -}; From b2a5db1d7ff6af339f3dcb128ad296404178e7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sat, 30 Nov 2019 14:04:22 +0100 Subject: [PATCH 18/41] test: report setting conversion results --- src/conversion/conversionResults.stubs.ts | 10 ++ src/reporting/reportConversionResults.ts | 2 + src/reporting/reportOutputs.ts | 16 +- .../reportSettingConversionResults.test.ts | 164 ++++++++++++++++++ 4 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 src/reporting/reportSettingConversionResults.test.ts diff --git a/src/conversion/conversionResults.stubs.ts b/src/conversion/conversionResults.stubs.ts index 57249adb2..e71c3a675 100644 --- a/src/conversion/conversionResults.stubs.ts +++ b/src/conversion/conversionResults.stubs.ts @@ -1,4 +1,5 @@ import { RuleConversionResults } from "../rules/convertRules"; +import { SettingConversionResults } from "../settings/convertSettings"; export const createEmptyConversionResults = ( overrides: Partial = {}, @@ -9,3 +10,12 @@ export const createEmptyConversionResults = ( plugins: new Set(), ...overrides, }); + +export const createEmptySettingConversionResults = ( + overrides: Partial = {}, +): SettingConversionResults => ({ + converted: new Map(), + failed: [], + missing: [], + ...overrides, +}); diff --git a/src/reporting/reportConversionResults.ts b/src/reporting/reportConversionResults.ts index a89d67c6f..581aa3a58 100644 --- a/src/reporting/reportConversionResults.ts +++ b/src/reporting/reportConversionResults.ts @@ -28,11 +28,13 @@ export const reportConversionResults = ( if (ruleConversionResults.missing.length !== 0) { const missingSettingOutputMapping = (setting: TSLintRuleOptions) => `${setting.ruleName} does not yet have an ESLint equivalent.${EOL}`; + const additionalWarnings = [`defaulting to eslint-plugin-tslint for these rules`]; logMissingConversionTarget( "rule", missingSettingOutputMapping, ruleConversionResults.missing, dependencies.logger, + additionalWarnings, ); } diff --git a/src/reporting/reportOutputs.ts b/src/reporting/reportOutputs.ts index 543f9ddfc..f4c9f2e48 100644 --- a/src/reporting/reportOutputs.ts +++ b/src/reporting/reportOutputs.ts @@ -34,6 +34,7 @@ export const logMissingConversionTarget = ( missingOutputMapping: (missing: T) => string, missing: T[], logger: Logger, + additionalWarnings: string[] = [], ) => { logger.stdout.write(chalk.yellowBright(`️👀 ${missing.length}`)); logger.stdout.write( @@ -43,11 +44,16 @@ export const logMissingConversionTarget = ( : ` ${conversionTypeName}s do not yet have ESLint equivalents`, ), ); - logger.stdout.write( - chalk.yellow( - ` (see generated log file); defaulting to eslint-plugin-tslint for these ${conversionTypeName}s.`, - ), - ); + logger.stdout.write(chalk.yellow(` (see generated log file)`)); + + if (additionalWarnings.length > 0) { + logger.stdout.write(chalk.yellow("; ")); + } + for (const warning of additionalWarnings) { + logger.stdout.write(chalk.yellow(warning)); + } + logger.stdout.write(chalk.yellow(".")); + logger.stdout.write(chalk.yellowBright(` 👀${EOL}`)); logger.info.write(missing.map(conversion => missingOutputMapping(conversion)).join("")); diff --git a/src/reporting/reportSettingConversionResults.test.ts b/src/reporting/reportSettingConversionResults.test.ts new file mode 100644 index 000000000..0b2198a09 --- /dev/null +++ b/src/reporting/reportSettingConversionResults.test.ts @@ -0,0 +1,164 @@ +import { EOL } from "os"; + +import { createStubLogger, expectEqualWrites } from "../adapters/logger.stubs"; +import { createEmptySettingConversionResults } from "../conversion/conversionResults.stubs"; +import { EditorSetting } from "../settings/types"; +import { reportSettingConversionResults } from "./reportSettingConversionResults"; + +describe("reportSettingConversionResults", () => { + it("logs a successful conversion when there is one converted setting", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + converted: new Map([ + [ + "tslint-setting-one", + { + settingName: "tslint-setting-one", + value: 42, + }, + ], + ]), + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stdout.write, + `✨ 1 setting replaced with its ESLint equivalent. ✨${EOL}`, + ); + }); + + it("logs successful conversions when there are multiple converted settings", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + converted: new Map([ + [ + "tslint-setting-one", + { + settingName: "tslint-setting-one", + value: 42, + }, + ], + [ + "tslint-setting-two", + { + settingName: "tslint-setting-two", + value: 4711, + }, + ], + ]), + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stdout.write, + `✨ 2 settings replaced with their ESLint equivalents. ✨${EOL}`, + ); + }); + + it("logs a failed conversion when there is one failed conversion", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + failed: [{ getSummary: () => "It broke." }], + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stderr.write, + "💀 1 error thrown. 💀", + `Check ${logger.debugFileName} for details.`, + ); + }); + + it("logs failed conversions when there are multiple failed conversions", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + failed: [{ getSummary: () => "It broke." }, { getSummary: () => "It really broke." }], + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stderr.write, + "💀 2 errors thrown. 💀", + `Check ${logger.debugFileName} for details.`, + ); + }); + + it("logs a missing setting when there is a missing setting", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + missing: [ + { + settingName: "tslint-setting-one", + value: "nothing-to-convert-to", + }, + ], + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stdout.write, + "👀 1 setting does not yet have an ESLint equivalent (see generated log file). 👀", + ); + expectEqualWrites( + logger.info.write, + "tslint-setting-one does not yet have an ESLint equivalent.", + ); + }); + + it("logs missing settings when there are missing settings", () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + missing: [ + { + settingName: "tslint-setting-one", + value: "nothing-to-convert-to", + }, + { + settingName: "tslint-setting-two", + value: 123, + }, + ], + }); + + const logger = createStubLogger(); + + // Act + reportSettingConversionResults({ logger }, conversionResults); + + // Assert + expectEqualWrites( + logger.stdout.write, + "👀 2 settings do not yet have ESLint equivalents (see generated log file). 👀", + ); + expectEqualWrites( + logger.info.write, + "tslint-setting-one does not yet have an ESLint equivalent.", + "tslint-setting-two does not yet have an ESLint equivalent.", + ); + }); +}); From 6e3cc18d8cc187437a552f1870edf6f28ab996ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sat, 30 Nov 2019 20:08:42 +0100 Subject: [PATCH 19/41] test: conversion of editor.codeActions source.fixAll.tslint into eslint.autoFixOnSave --- .../tests/editor-code-actions-on-save.test.ts | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/settings/converters/tests/editor-code-actions-on-save.test.ts diff --git a/src/settings/converters/tests/editor-code-actions-on-save.test.ts b/src/settings/converters/tests/editor-code-actions-on-save.test.ts new file mode 100644 index 000000000..09231f2ea --- /dev/null +++ b/src/settings/converters/tests/editor-code-actions-on-save.test.ts @@ -0,0 +1,74 @@ +import { convertEditorCodeActionsOnSave } from "../editor-code-actions-on-save"; + +describe(convertEditorCodeActionsOnSave, () => { + test("conversion of 'source.fixAll.tslint' when value is true", () => { + const result = convertEditorCodeActionsOnSave({ + settingName: "editor.codeActionsOnSave", + value: { + "source.fixAll.tslint": true, + }, + }); + + expect(result).toEqual({ + settings: [ + { + settingName: "editor.codeActionsOnSave", + value: {}, + }, + { + settingName: "eslint.autoFixOnSave", + value: true, + }, + ], + }); + }); + + test("conversion of 'source.fixAll.tslint' when value is false", () => { + const result = convertEditorCodeActionsOnSave({ + settingName: "editor.codeActionsOnSave", + value: { + "source.fixAll.tslint": false, + }, + }); + + expect(result).toEqual({ + settings: [ + { + settingName: "editor.codeActionsOnSave", + value: {}, + }, + { + settingName: "eslint.autoFixOnSave", + value: false, + }, + ], + }); + }); + + test("conversion of 'source.fixAll.tslint' without touching any other 'editor.codeActionsOnSave'", () => { + const result = convertEditorCodeActionsOnSave({ + settingName: "editor.codeActionsOnSave", + value: { + "one-property": 42, + "source.fixAll.tslint": true, + "another-property": "foo", + }, + }); + + expect(result).toEqual({ + settings: [ + { + settingName: "editor.codeActionsOnSave", + value: { + "one-property": 42, + "another-property": "foo", + }, + }, + { + settingName: "eslint.autoFixOnSave", + value: true, + }, + ], + }); + }); +}); From fe3034bc41dc3b0e944288292a0070d1037e2def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sat, 30 Nov 2019 20:17:23 +0100 Subject: [PATCH 20/41] test: convert setting --- src/settings/convertSetting.test.ts | 73 +++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/settings/convertSetting.test.ts diff --git a/src/settings/convertSetting.test.ts b/src/settings/convertSetting.test.ts new file mode 100644 index 000000000..819e7c75c --- /dev/null +++ b/src/settings/convertSetting.test.ts @@ -0,0 +1,73 @@ +import { ConversionError } from "../errors/conversionError"; +import { EditorSettingConverter } from "./converter"; +import { convertSetting } from "./convertSetting"; +import { EditorSetting } from "./types"; + +describe("convertSetting", () => { + it("returns undefined when no converter exists for a setting", () => { + // Arrange + const converters = new Map(); + + // Act + const result = convertSetting( + { + settingName: "tslint-setting", + value: "any value", + }, + converters, + ); + + // Assert + expect(result).toEqual(undefined); + }); + + it("returns converter results when the converter does not throw an error", () => { + // Arrange + const converted = { + settings: [ + { + settingName: "eslint-setting", + value: "new value", + }, + ], + }; + const converters = new Map([ + ["tslint-setting", () => converted], + ]); + + // Act + const result = convertSetting( + { + settingName: "tslint-setting", + value: "existing value", + }, + converters, + ); + + // Assert + expect(result).toEqual(converted); + }); + + it("returns a conversion error when the converter throws an error", () => { + // Arrange + const error = new Error("oh no"); + const converters = new Map([ + [ + "tslint-setting", + () => { + throw error; + }, + ], + ]); + const tsLintSetting: EditorSetting = { + settingName: "tslint-setting", + value: "existing value", + }; + + // Act + const result = convertSetting(tsLintSetting, converters); + + // Assert + expect(result).toEqual(ConversionError.forSettingError(error, tsLintSetting)); + }); +}); From 186c12847edaf52b36226cfe2fbc18e84cba58bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 1 Dec 2019 14:46:19 +0100 Subject: [PATCH 21/41] test: convert settings, adjust missing and converted conversion results --- .../reportSettingConversionResults.test.ts | 3 - .../reportSettingConversionResults.ts | 2 +- src/settings/convertSettings.test.ts | 95 +++++++++++++++++++ src/settings/convertSettings.ts | 9 +- 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 src/settings/convertSettings.test.ts diff --git a/src/reporting/reportSettingConversionResults.test.ts b/src/reporting/reportSettingConversionResults.test.ts index 0b2198a09..2fb953b5a 100644 --- a/src/reporting/reportSettingConversionResults.test.ts +++ b/src/reporting/reportSettingConversionResults.test.ts @@ -109,7 +109,6 @@ describe("reportSettingConversionResults", () => { missing: [ { settingName: "tslint-setting-one", - value: "nothing-to-convert-to", }, ], }); @@ -136,11 +135,9 @@ describe("reportSettingConversionResults", () => { missing: [ { settingName: "tslint-setting-one", - value: "nothing-to-convert-to", }, { settingName: "tslint-setting-two", - value: 123, }, ], }); diff --git a/src/reporting/reportSettingConversionResults.ts b/src/reporting/reportSettingConversionResults.ts index db71bf2c9..3ec74c076 100644 --- a/src/reporting/reportSettingConversionResults.ts +++ b/src/reporting/reportSettingConversionResults.ts @@ -26,7 +26,7 @@ export const reportSettingConversionResults = ( } if (settingConversionResults.missing.length !== 0) { - const missingSettingOutputMapping = (setting: EditorSetting) => + const missingSettingOutputMapping = (setting: Pick) => `${setting.settingName} does not yet have an ESLint equivalent.${EOL}`; logMissingConversionTarget( "setting", diff --git a/src/settings/convertSettings.test.ts b/src/settings/convertSettings.test.ts new file mode 100644 index 000000000..23cc08eb9 --- /dev/null +++ b/src/settings/convertSettings.test.ts @@ -0,0 +1,95 @@ +import { ConversionError } from "../errors/conversionError"; +import { convertSettings } from "./convertSettings"; +import { EditorSetting } from "./types"; +import { EditorSettingConverter, EditorSettingConversionResult } from "./converter"; + +describe("convertSettings", () => { + it("marks a setting as missing when its converter returns undefined", () => { + // Arrange + const { editorSetting, converters } = setupConversionEnvironment(); + + // Act + const { missing } = convertSettings( + { converters }, + { [editorSetting.settingName]: editorSetting }, + ); + + // Assert + expect(missing).toEqual([{ settingName: editorSetting.settingName }]); + }); + + it("marks a conversion as failed when returned a conversion error", () => { + // Arrange + const { editorSetting, converters } = setupConversionEnvironment(); + const conversionError = ConversionError.forSettingError(new Error(), editorSetting); + converters.set(editorSetting.settingName, () => conversionError); + + // Act + const { failed } = convertSettings( + { converters }, + { [editorSetting.settingName]: editorSetting }, + ); + + // Assert + expect(failed).toEqual([conversionError]); + }); + + it("marks a converted setting name as converted when a conversion has settings", () => { + // Arrange + const conversionResult: EditorSettingConversionResult = { + settings: [ + { + settingName: "eslint-setting-a", + value: "a", + }, + ], + }; + const { editorSetting, converters } = setupConversionEnvironment(conversionResult); + + // Act + const { converted } = convertSettings( + { converters }, + { [editorSetting.settingName]: editorSetting.value }, + ); + + // Assert + expect(converted).toEqual( + new Map([ + [ + "tslint-setting-a", + { + settingName: "eslint-setting-a", + value: "a", + }, + ], + ]), + ); + }); +}); + +function setupConversionEnvironment(conversionResult?: EditorSettingConversionResult) { + const editorSetting = createSampleEditorSetting(); + const converters = createConverters(editorSetting, conversionResult); + + return { editorSetting, converters }; +} + +function createSampleEditorSetting(): EditorSetting { + return { + settingName: "tslint-setting-a", + value: "a", + }; +} + +function createConverters( + tslintSetting: EditorSetting, + conversionResult?: EditorSettingConversionResult, +): Map { + const converters = new Map(); + + if (conversionResult !== undefined) { + converters.set(tslintSetting.settingName, () => conversionResult); + } + + return converters; +} diff --git a/src/settings/convertSettings.ts b/src/settings/convertSettings.ts index 714a75400..e7ced8fe0 100644 --- a/src/settings/convertSettings.ts +++ b/src/settings/convertSettings.ts @@ -11,7 +11,7 @@ export type ConvertSettingsDependencies = { export type SettingConversionResults = { converted: Map; failed: ErrorSummary[]; - missing: EditorSetting[]; + missing: Pick[]; }; export type EditorConfigurationSettings = Record; @@ -22,14 +22,15 @@ export const convertSettings = ( ): SettingConversionResults => { const converted = new Map(); const failed: ConversionError[] = []; - const missing: EditorSetting[] = []; + const missing: Pick[] = []; for (const [settingName, value] of Object.entries(rawEditorSettings)) { const editorSetting = { settingName, value }; const conversion = convertSetting(editorSetting, dependencies.converters); if (conversion === undefined) { - missing.push(editorSetting); + const { settingName } = editorSetting; + missing.push({ settingName }); continue; } @@ -43,7 +44,7 @@ export const convertSettings = ( const newConversion = { ...changes }; if (existingConversion === undefined) { - converted.set(changes.settingName, newConversion); + converted.set(settingName, newConversion); continue; } } From 1d427ee52f4bd6a718efb990ca81b10e1eeee1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 1 Dec 2019 14:50:16 +0100 Subject: [PATCH 22/41] test: exlcude settings converters from coverage --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index f329ba374..d4eb8aae8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,6 +5,7 @@ module.exports = { "!./src/**/*.stubs.ts", "!./src/adapters/*.ts", "!./src/rules/converters.ts", + "!./src/settings/converters.ts", "!./src/rules/mergers.ts", "!./src/cli/main.ts", ], From 9eb78432468b2d4c5709f11fbc0b0594c59340fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Sun, 1 Dec 2019 15:35:54 +0100 Subject: [PATCH 23/41] test: find editor configuration, stub file system --- src/adapters/fileSystem.stub.ts | 11 +++ src/input/findEditorConfiguration.test.ts | 94 +++++++++++++++++++++++ src/input/findEditorConfiguration.ts | 6 +- 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/adapters/fileSystem.stub.ts create mode 100644 src/input/findEditorConfiguration.test.ts diff --git a/src/adapters/fileSystem.stub.ts b/src/adapters/fileSystem.stub.ts new file mode 100644 index 000000000..eb1fdcc00 --- /dev/null +++ b/src/adapters/fileSystem.stub.ts @@ -0,0 +1,11 @@ +export const createStubFileSystem = ({ data = {}, exists = true } = {}) => ({ + fileExists: jest.fn().mockReturnValue(exists), + readFile: jest.fn().mockReturnValue(Promise.resolve(data)), + writeFile: jest.fn(), +}); + +export const createStubThrowingFileSystem = ({ err = "" } = {}) => ({ + fileExists: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))), + readFile: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))), + writeFile: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))), +}); diff --git a/src/input/findEditorConfiguration.test.ts b/src/input/findEditorConfiguration.test.ts new file mode 100644 index 000000000..49bedd548 --- /dev/null +++ b/src/input/findEditorConfiguration.test.ts @@ -0,0 +1,94 @@ +import { createStubFileSystem, createStubThrowingFileSystem } from "../adapters/fileSystem.stub"; +import { + findEditorConfiguration, + FindEditorConfigurationDependencies, +} from "./findEditorConfiguration"; + +const createStubDependencies = (overrides: Partial = {}) => ({ + fileSystem: createStubFileSystem(), + ...overrides, +}); + +const stubConfigPath = "temp/"; + +describe("findEditorConfiguration", () => { + it("returns an error when fileSystem returns one", async () => { + // Arrange + const message = "error"; + const dependencies = createStubDependencies({ + fileSystem: createStubFileSystem({ data: new Error(message) }), + }); + + // Act + const result = await findEditorConfiguration(dependencies, stubConfigPath); + + // Assert + expect(result).toEqual( + expect.objectContaining({ + message, + }), + ); + }); + + it("returns an error when fileSystem throws one", async () => { + // Arrange + const message = "error"; + const dependencies = createStubDependencies({ + fileSystem: createStubThrowingFileSystem({ err: message }), + }); + + // Act + const result = await findEditorConfiguration(dependencies, stubConfigPath); + + // Assert + expect(result).toEqual( + expect.objectContaining({ + message, + }), + ); + }); + + it("reads from the given configuration path when one is provided", async () => { + // Arrange + const configPath = "/thePath"; + const dependencies = createStubDependencies(); + + // Act + await findEditorConfiguration(dependencies, configPath); + + // Assert + expect(dependencies.fileSystem.readFile).toHaveBeenLastCalledWith(configPath); + }); + + it("defaults to VS Code editor settings path when config path isn't provided", async () => { + // Arrange + const dependencies = createStubDependencies(); + + // Act + await findEditorConfiguration(dependencies, undefined); + + // Assert + expect(dependencies.fileSystem.readFile).toHaveBeenLastCalledWith(".vscode/settings.json"); + }); + + it("parses object from configuration path when read successfully", async () => { + // Arrange + const config = { + "typescript.tsdk": "node_modules/typescript/lib", + "editor.tabSize": 4, + "editor.codeActionsOnSave": { + "source.organizeImports": false, + }, + }; + const data = JSON.stringify(config); + const dependencies = createStubDependencies({ + fileSystem: createStubFileSystem({ data }), + }); + + // Act + const result = await findEditorConfiguration(dependencies, stubConfigPath); + + // Assert + expect(result).toEqual(config); + }); +}); diff --git a/src/input/findEditorConfiguration.ts b/src/input/findEditorConfiguration.ts index 6ae240171..d4449f942 100644 --- a/src/input/findEditorConfiguration.ts +++ b/src/input/findEditorConfiguration.ts @@ -1,7 +1,7 @@ import { FileSystem } from "../adapters/fileSystem"; import { EditorConfiguration } from "./editorConfiguration"; -import { DEFAULT_VSCODE_SETTINGS_PATH } from "./vsCodeSettings"; import { DeepPartial } from "./findReportedConfiguration"; +import { DEFAULT_VSCODE_SETTINGS_PATH } from "./vsCodeSettings"; export type FindEditorConfigurationDependencies = { fileSystem: Pick; @@ -26,10 +26,10 @@ const readConfiguration = async ( try { const fileContents = await fileSystem.readFile(path); if (fileContents instanceof Error) { - throw new Error(path); + throw new Error(fileContents.message); } return JSON.parse(fileContents) as DeepPartial; } catch (error) { - return new Error(`Error parsing configuration: ${error}`); + return error; } }; From 98cc72c54dac034453f44fe32c67521e75c78c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 3 Dec 2019 22:41:56 +0100 Subject: [PATCH 24/41] feat: simplify convertSettings because multiple setting changes don't apply yet --- src/settings/convertSettings.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/settings/convertSettings.ts b/src/settings/convertSettings.ts index e7ced8fe0..59896678d 100644 --- a/src/settings/convertSettings.ts +++ b/src/settings/convertSettings.ts @@ -40,13 +40,7 @@ export const convertSettings = ( } for (const changes of conversion.settings) { - const existingConversion = converted.get(changes.settingName); - const newConversion = { ...changes }; - - if (existingConversion === undefined) { - converted.set(settingName, newConversion); - continue; - } + converted.set(settingName, { ...changes }); } } From 83b9dccbf851bcf0e61cf3c6be4326129438bcaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 3 Dec 2019 23:00:38 +0100 Subject: [PATCH 25/41] refactor: adjust naming of test variable --- src/input/findEditorConfiguration.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/input/findEditorConfiguration.test.ts b/src/input/findEditorConfiguration.test.ts index 49bedd548..61f16c500 100644 --- a/src/input/findEditorConfiguration.test.ts +++ b/src/input/findEditorConfiguration.test.ts @@ -73,14 +73,14 @@ describe("findEditorConfiguration", () => { it("parses object from configuration path when read successfully", async () => { // Arrange - const config = { + const originalConfig = { "typescript.tsdk": "node_modules/typescript/lib", "editor.tabSize": 4, "editor.codeActionsOnSave": { "source.organizeImports": false, }, }; - const data = JSON.stringify(config); + const data = JSON.stringify(originalConfig); const dependencies = createStubDependencies({ fileSystem: createStubFileSystem({ data }), }); @@ -89,6 +89,6 @@ describe("findEditorConfiguration", () => { const result = await findEditorConfiguration(dependencies, stubConfigPath); // Assert - expect(result).toEqual(config); + expect(result).toEqual(originalConfig); }); }); From 85b1e257e0470b4ea01fbbdda9dd53d0972b2123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Tue, 3 Dec 2019 23:01:21 +0100 Subject: [PATCH 26/41] test: write editor config conversion results to proper path --- ...writeEditorConfigConversionResults.test.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/creation/writeEditorConfigConversionResults.test.ts diff --git a/src/creation/writeEditorConfigConversionResults.test.ts b/src/creation/writeEditorConfigConversionResults.test.ts new file mode 100644 index 000000000..d3c62b07f --- /dev/null +++ b/src/creation/writeEditorConfigConversionResults.test.ts @@ -0,0 +1,47 @@ +import { createStubFileSystem } from "../adapters/fileSystem.stub"; +import { createEmptySettingConversionResults } from "../conversion/conversionResults.stubs"; +import { EditorSetting } from "../settings/types"; +import { + writeConversionResults, + WriteConversionResultsDependencies, +} from "./writeEditorConfigConversionResults"; + +const createStubDependencies = (overrides: Partial = {}) => ({ + fileSystem: createStubFileSystem(), + ...overrides, +}); + +describe("writeConversionResults", () => { + it("write with file system to correct output path", async () => { + // Arrange + const originalConfig = { + "typescript.tsdk": "node_modules/typescript/lib", + "editor.tabSize": 4, + "editor.codeActionsOnSave": { + "source.organizeImports": false, + }, + }; + const outputPath = "/temp"; + const dependencies = createStubDependencies(); + const conversionResults = createEmptySettingConversionResults({ + converted: new Map([ + [ + "tslint-setting-one", + { + settingName: "tslint-setting-one", + value: 42, + }, + ], + ]), + }); + + // Act + await writeConversionResults(dependencies, outputPath, conversionResults, originalConfig); + + // Assert + expect(dependencies.fileSystem.writeFile).toHaveBeenCalledWith( + outputPath, + expect.anything(), + ); + }); +}); From 7d6ce31a19067528add6c8f189e8de7d7b356bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Wed, 4 Dec 2019 05:54:53 +0100 Subject: [PATCH 27/41] test: write editor config output with sorted keys to file system --- ...writeEditorConfigConversionResults.test.ts | 107 +++++++++++++++--- 1 file changed, 89 insertions(+), 18 deletions(-) diff --git a/src/creation/writeEditorConfigConversionResults.test.ts b/src/creation/writeEditorConfigConversionResults.test.ts index d3c62b07f..c66a1a6e6 100644 --- a/src/creation/writeEditorConfigConversionResults.test.ts +++ b/src/creation/writeEditorConfigConversionResults.test.ts @@ -1,6 +1,10 @@ import { createStubFileSystem } from "../adapters/fileSystem.stub"; import { createEmptySettingConversionResults } from "../conversion/conversionResults.stubs"; +import { EditorConfiguration } from "../input/editorConfiguration"; +import { DeepPartial } from "../input/findReportedConfiguration"; +import { SettingConversionResults } from "../settings/convertSettings"; import { EditorSetting } from "../settings/types"; +import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput"; import { writeConversionResults, WriteConversionResultsDependencies, @@ -12,18 +16,93 @@ const createStubDependencies = (overrides: Partial { - it("write with file system to correct output path", async () => { + it("writes to correct output path with file system", async () => { // Arrange - const originalConfig = { + const dependencies = createStubDependencies(); + const outputPath = "/temp"; + const { originalConfig, conversionResults } = setupConversionEnvironment(); + + // Act + await writeConversionResults(dependencies, outputPath, conversionResults, originalConfig); + + // Assert + expect(dependencies.fileSystem.writeFile).toHaveBeenCalledWith( + outputPath, + expect.anything(), + ); + }); + + it("writes formatted output with sorted keys to file system", async () => { + // Arrange + const dependencies = createStubDependencies(); + const outputPath = "/temp"; + + const { originalConfig, conversionResults } = setupConversionEnvironment({ + originalConfig: { + "property.a": "someValue", + "property.c": 123, + "property.b": { + "unsorted.sub.property.b": false, + "unsorted.sub.property.a": false, + }, + }, + conversionResults: createEmptySettingConversionResults({ + converted: new Map([ + [ + "eslint-setting-b", + { + settingName: "eslint-setting-b", + value: 42, + }, + ], + [ + "eslint-setting-a", + { + settingName: "eslint-setting-a", + value: 4711, + }, + ], + ]), + }), + }); + + const expectedSortedOutput = formatJsonOutput({ + "eslint-setting-a": 4711, + "eslint-setting-b": 42, + "property.a": "someValue", + "property.b": { + "unsorted.sub.property.b": false, + "unsorted.sub.property.a": false, + }, + "property.c": 123, + }); + + // Act + await writeConversionResults(dependencies, outputPath, conversionResults, originalConfig); + + // Assert + expect(dependencies.fileSystem.writeFile).toHaveBeenCalledWith( + expect.anything(), + expectedSortedOutput, + ); + }); +}); + +function setupConversionEnvironment( + overrides: { + conversionResults?: SettingConversionResults; + originalConfig?: DeepPartial; + } = {}, +) { + return { + originalConfig: { "typescript.tsdk": "node_modules/typescript/lib", "editor.tabSize": 4, "editor.codeActionsOnSave": { "source.organizeImports": false, }, - }; - const outputPath = "/temp"; - const dependencies = createStubDependencies(); - const conversionResults = createEmptySettingConversionResults({ + }, + conversionResults: createEmptySettingConversionResults({ converted: new Map([ [ "tslint-setting-one", @@ -33,15 +112,7 @@ describe("writeConversionResults", () => { }, ], ]), - }); - - // Act - await writeConversionResults(dependencies, outputPath, conversionResults, originalConfig); - - // Assert - expect(dependencies.fileSystem.writeFile).toHaveBeenCalledWith( - outputPath, - expect.anything(), - ); - }); -}); + }), + ...overrides, + }; +} From d63d03b4275885220d46da6eba5e8845e36dae5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Wed, 4 Dec 2019 06:24:49 +0100 Subject: [PATCH 28/41] test: conversion of editor config --- src/conversion/convertEditorConfig.test.ts | 137 +++++++++++++++++++++ src/conversion/convertEditorConfig.ts | 9 +- 2 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/conversion/convertEditorConfig.test.ts diff --git a/src/conversion/convertEditorConfig.test.ts b/src/conversion/convertEditorConfig.test.ts new file mode 100644 index 000000000..d5ad4dfe1 --- /dev/null +++ b/src/conversion/convertEditorConfig.test.ts @@ -0,0 +1,137 @@ +import { EditorSetting } from "../settings/types"; +import { FailedResult, ResultStatus } from "../types"; +import { createEmptySettingConversionResults } from "./conversionResults.stubs"; +import { convertEditorConfig, ConvertEditorConfigDependencies } from "./convertEditorConfig"; + +const stubSettings = { + config: "./eslintrc.js", + editor: "./my-editor/settings.json", +}; + +const createStubDependencies = ( + overrides: Partial = {}, +): ConvertEditorConfigDependencies => ({ + convertSettings: jest.fn(), + findEditorConfiguration: jest.fn().mockResolvedValue({}), + reportConversionResults: jest.fn(), + writeConversionResults: jest.fn().mockReturnValue(Promise.resolve()), + ...overrides, +}); + +describe("convertEditorConfig", () => { + it("returns the failure result when finding the original configurations fails", async () => { + // Arrange + const error = new Error(); + const findError: FailedResult = { + errors: [error], + status: ResultStatus.Failed, + }; + + const dependencies = createStubDependencies({ + findEditorConfiguration: async () => error, + }); + + // Act + const result = await convertEditorConfig(dependencies, stubSettings); + + // Assert + expect(result).toEqual(findError); + }); + + it("returns the failure result when writing to the configuration file fails", async () => { + // Arrange + const fileWriteError = new Error(); + const dependencies = createStubDependencies({ + writeConversionResults: jest.fn().mockResolvedValueOnce(fileWriteError), + }); + + // Act + const result = await convertEditorConfig(dependencies, stubSettings); + + // Assert + expect(result).toEqual({ + errors: [fileWriteError], + status: ResultStatus.Failed, + }); + }); + + it("converts conversion results when finding the original configurations succeeds", async () => { + // Arrange + const originalConfig = { + "typescript.tsdk": "node_modules/typescript/lib", + "editor.tabSize": 4, + "editor.codeActionsOnSave": { + "source.organizeImports": false, + }, + }; + + const dependencies = createStubDependencies({ + findEditorConfiguration: jest.fn().mockResolvedValue(originalConfig), + }); + + // Act + await convertEditorConfig(dependencies, stubSettings); + + // Assert + expect(dependencies.convertSettings).toHaveBeenCalledWith(originalConfig); + }); + + it("reports conversion results when settings are converted successfully", async () => { + // Arrange + const conversionResults = createEmptySettingConversionResults({ + converted: new Map([ + [ + "tslint-setting-one", + { + settingName: "tslint-setting-one", + value: 42, + }, + ], + ]), + }); + + const dependencies = createStubDependencies({ + convertSettings: jest.fn().mockReturnValue(conversionResults), + }); + + // Act + await convertEditorConfig(dependencies, stubSettings); + + // Assert + expect(dependencies.reportConversionResults).toHaveBeenCalledWith(conversionResults); + }); + + it("returns a successful result when finding the original configurations succeeds", async () => { + // Arrange + const dependencies = createStubDependencies(); + + // Act + const result = await convertEditorConfig(dependencies, stubSettings); + + // Assert + expect(result).toEqual({ + status: ResultStatus.Succeeded, + }); + }); + + it("uses VS Code default settings path if editor config parameter is undefined", async () => { + // Arrange + const expectedEditorPath = ".vscode/settings.json"; + const settings = { + config: "./eslintrc.js", + }; + + const dependencies = createStubDependencies(); + + // Act + await convertEditorConfig(dependencies, settings); + + // Assert + expect(dependencies.findEditorConfiguration).toHaveBeenCalledWith(expectedEditorPath); + // expect(dependencies.writeConversionResults).toHaveBeenCalledWith( + // expectedEditorPath, + // expect.anything(), + // expect.anything(), + // ); + }); +}); diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 1319bdac5..459046c7f 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -2,9 +2,9 @@ import { SansDependencies } from "../binding"; import { writeConversionResults } from "../creation/writeEditorConfigConversionResults"; import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings"; +import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; import { convertSettings } from "../settings/convertSettings"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; -import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; export type ConvertEditorConfigDependencies = { convertSettings: SansDependencies; @@ -20,7 +20,10 @@ export const convertEditorConfig = async ( dependencies: ConvertEditorConfigDependencies, settings: TSLintToESLintSettings, ): Promise => { - const originalEditorConfiguration = await dependencies.findEditorConfiguration(settings.editor); + const editorConfigPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; + const originalEditorConfiguration = await dependencies.findEditorConfiguration( + editorConfigPath, + ); if (originalEditorConfiguration instanceof Error) { return { errors: [originalEditorConfiguration], @@ -30,7 +33,7 @@ export const convertEditorConfig = async ( const settingConversionResults = dependencies.convertSettings(originalEditorConfiguration); - const outputPath = settings.editor ? settings.editor : DEFAULT_VSCODE_SETTINGS_PATH; + const outputPath = editorConfigPath; const fileWriteError = await dependencies.writeConversionResults( outputPath, settingConversionResults, From 53f858d2bdd1496961157547433a3c63002f79d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 11:29:56 +0100 Subject: [PATCH 29/41] refactor: change generics into actual types --- src/reporting/reportOutputs.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/reporting/reportOutputs.ts b/src/reporting/reportOutputs.ts index f4c9f2e48..ce59760c1 100644 --- a/src/reporting/reportOutputs.ts +++ b/src/reporting/reportOutputs.ts @@ -3,10 +3,14 @@ import { EOL } from "os"; import { Logger } from "../adapters/logger"; import { ErrorSummary } from "../errors/errorSummary"; +import { ESLintRuleOptions } from "../rules/types"; +import { EditorSetting } from "../settings/types"; -export const logSuccessfulConversions = ( +export type EditorSettingEntry = Pick; + +export const logSuccessfulConversions = ( conversionTypeName: string, - converted: Map, + converted: Map, logger: Logger, ) => { logger.stdout.write(chalk.greenBright(`✨ ${converted.size}`)); From 75ba2daf05e8a7d8f25e299e814a62af8014b7a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 11:45:32 +0100 Subject: [PATCH 30/41] refactor: rename converters to specific rulesConverters and settingsConverters --- src/cli/main.ts | 24 +++++++++---------- .../{converters.ts => rulesConverters.ts} | 2 +- .../{converters.ts => settingsConverters.ts} | 4 +++- 3 files changed, 16 insertions(+), 14 deletions(-) rename src/rules/{converters.ts => rulesConverters.ts} (99%) rename src/settings/{converters.ts => settingsConverters.ts} (62%) diff --git a/src/cli/main.ts b/src/cli/main.ts index f56aa08d9..b6a2b1a68 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -5,15 +5,15 @@ import { fsFileSystem } from "../adapters/fsFileSystem"; import { nativeImporter } from "../adapters/nativeImporter"; import { processLogger } from "../adapters/processLogger"; import { bind } from "../binding"; -import { ConvertConfigDependencies, convertConfig } from "../conversion/convertConfig"; +import { convertConfig, ConvertConfigDependencies } from "../conversion/convertConfig"; import { - ConvertEditorConfigDependencies, convertEditorConfig, + ConvertEditorConfigDependencies, } from "../conversion/convertEditorConfig"; import { removeExtendsDuplicatedRules } from "../creation/simplification/removeExtendsDuplicatedRules"; import { - RetrieveExtendsValuesDependencies, retrieveExtendsValues, + RetrieveExtendsValuesDependencies, } from "../creation/simplification/retrieveExtendsValues"; import { simplifyPackageRules, @@ -24,34 +24,34 @@ import { WriteConversionResultsDependencies, } from "../creation/writeConversionResults"; import { writeConversionResults as writeEditorConfigConversionResults } from "../creation/writeEditorConfigConversionResults"; +import { findEditorConfiguration } from "../input/findEditorConfiguration"; +import { findESLintConfiguration } from "../input/findESLintConfiguration"; import { findOriginalConfigurations, FindOriginalConfigurationsDependencies, } from "../input/findOriginalConfigurations"; import { findPackagesConfiguration } from "../input/findPackagesConfiguration"; -import { findESLintConfiguration } from "../input/findESLintConfiguration"; import { findTSLintConfiguration } from "../input/findTSLintConfiguration"; import { findTypeScriptConfiguration } from "../input/findTypeScriptConfiguration"; -import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { importer, ImporterDependencies } from "../input/importer"; import { mergeLintConfigurations } from "../input/mergeLintConfigurations"; -import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; -import { reportConversionResults } from "../reporting/reportConversionResults"; import { ReportConversionResultsDependencies } from "../reporting/dependencies"; -import { converters as rulesConverters } from "../rules/converters"; -import { converters as settingsConverters } from "../settings/converters"; +import { reportConversionResults } from "../reporting/reportConversionResults"; +import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; import { convertRules } from "../rules/convertRules"; import { mergers } from "../rules/mergers"; -import { runCli, RunCliDependencies } from "./runCli"; +import { rulesConverters } from "../rules/rulesConverters"; import { convertSettings } from "../settings/convertSettings"; +import { settingsConverters } from "../settings/settingsConverters"; +import { runCli, RunCliDependencies } from "./runCli"; const convertRulesDependencies = { - converters: rulesConverters, + rulesConverters, mergers, }; const convertSettingsDependencies = { - converters: settingsConverters, + settingsConverters, }; const nativeImporterDependencies: ImporterDependencies = { diff --git a/src/rules/converters.ts b/src/rules/rulesConverters.ts similarity index 99% rename from src/rules/converters.ts rename to src/rules/rulesConverters.ts index 4a4ce1a1f..ef05aba04 100644 --- a/src/rules/converters.ts +++ b/src/rules/rulesConverters.ts @@ -133,7 +133,7 @@ import { convertVariableName } from "./converters/variable-name"; /** * Keys TSLint rule names to their ESLint rule converters. */ -export const converters = new Map([ +export const rulesConverters = new Map([ ["adjacent-overload-signatures", convertAdjacentOverloadSignatures], ["align", convertAlign], ["array-type", convertArrayType], diff --git a/src/settings/converters.ts b/src/settings/settingsConverters.ts similarity index 62% rename from src/settings/converters.ts rename to src/settings/settingsConverters.ts index 9e5cea6f2..76c9b9095 100644 --- a/src/settings/converters.ts +++ b/src/settings/settingsConverters.ts @@ -3,4 +3,6 @@ import { convertEditorCodeActionsOnSave } from "./converters/editor-code-actions /** * Keys TSLint property names in editor settings to their ESLint editor settings converters. */ -export const converters = new Map([["editor.codeActionsOnSave", convertEditorCodeActionsOnSave]]); +export const settingsConverters = new Map([ + ["editor.codeActionsOnSave", convertEditorCodeActionsOnSave], +]); From a8af16e4fbf8d12ec0caeb8ee3d9c9119b387a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 11:53:16 +0100 Subject: [PATCH 31/41] test: clean up outcommented code --- src/conversion/convertEditorConfig.test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/conversion/convertEditorConfig.test.ts b/src/conversion/convertEditorConfig.test.ts index d5ad4dfe1..a5f3fed78 100644 --- a/src/conversion/convertEditorConfig.test.ts +++ b/src/conversion/convertEditorConfig.test.ts @@ -128,10 +128,5 @@ describe("convertEditorConfig", () => { // Assert expect(dependencies.findEditorConfiguration).toHaveBeenCalledWith(expectedEditorPath); - // expect(dependencies.writeConversionResults).toHaveBeenCalledWith( - // expectedEditorPath, - // expect.anything(), - // expect.anything(), - // ); }); }); From 5e6879ee8eb05411d9acebb125d9dd810fe0ce81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 11:57:03 +0100 Subject: [PATCH 32/41] fix: change ignored coverage path --- jest.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jest.config.js b/jest.config.js index d4eb8aae8..5da25e8ba 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,8 +4,8 @@ module.exports = { "!./src/**/*.d.ts", "!./src/**/*.stubs.ts", "!./src/adapters/*.ts", - "!./src/rules/converters.ts", - "!./src/settings/converters.ts", + "!./src/rules/rulesConverters.ts", + "!./src/settings/settingsConverters.ts", "!./src/rules/mergers.ts", "!./src/cli/main.ts", ], From 03e837273c0ca8e8e25c12ef1ffa0f57306f1a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 15:32:03 +0100 Subject: [PATCH 33/41] fix: add typing and dependency property name --- src/cli/main.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cli/main.ts b/src/cli/main.ts index b6a2b1a68..8321dd763 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -38,20 +38,20 @@ import { mergeLintConfigurations } from "../input/mergeLintConfigurations"; import { ReportConversionResultsDependencies } from "../reporting/dependencies"; import { reportConversionResults } from "../reporting/reportConversionResults"; import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; -import { convertRules } from "../rules/convertRules"; +import { convertRules, ConvertRulesDependencies } from "../rules/convertRules"; import { mergers } from "../rules/mergers"; import { rulesConverters } from "../rules/rulesConverters"; -import { convertSettings } from "../settings/convertSettings"; +import { convertSettings, ConvertSettingsDependencies } from "../settings/convertSettings"; import { settingsConverters } from "../settings/settingsConverters"; import { runCli, RunCliDependencies } from "./runCli"; -const convertRulesDependencies = { - rulesConverters, +const convertRulesDependencies: ConvertRulesDependencies = { + converters: rulesConverters, mergers, }; -const convertSettingsDependencies = { - settingsConverters, +const convertSettingsDependencies: ConvertSettingsDependencies = { + converters: settingsConverters, }; const nativeImporterDependencies: ImporterDependencies = { From b339028dd3ff26f58d0d2f91ab45f7ab857b070d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 15:58:31 +0100 Subject: [PATCH 34/41] fix: only convert editor settings from the editor configuration --- src/settings/convertSettings.test.ts | 53 +++++++++++++++++++++++++--- src/settings/convertSettings.ts | 19 +++++++--- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/settings/convertSettings.test.ts b/src/settings/convertSettings.test.ts index 23cc08eb9..c37b2ef64 100644 --- a/src/settings/convertSettings.test.ts +++ b/src/settings/convertSettings.test.ts @@ -4,6 +4,51 @@ import { EditorSetting } from "./types"; import { EditorSettingConverter, EditorSettingConversionResult } from "./converter"; describe("convertSettings", () => { + it("skips entire conversion if none of the configurations is an editor setting", () => { + // Arrange + const { converters } = setupConversionEnvironment(); + + const editorConfiguration = { + notAnEditorSetting: "a", + }; + + // Act + const { converted, missing, failed } = convertSettings({ converters }, editorConfiguration); + + // Assert + expect(converted.size).toEqual(0); + expect(missing.length).toEqual(0); + expect(failed.length).toEqual(0); + }); + + it("skips a configuration if not an editor setting", () => { + // Arrange + const conversionResult: EditorSettingConversionResult = { + settings: [ + { + settingName: "editor.eslint-setting-a", + value: "a", + }, + ], + }; + + const { editorSetting, converters } = setupConversionEnvironment(conversionResult); + + const editorConfiguration = { + notAnEditorSetting: "a", + [editorSetting.settingName]: editorSetting, + notAnEditorSettingEither: "b", + }; + + // Act + const { converted, missing, failed } = convertSettings({ converters }, editorConfiguration); + + // Assert + expect(converted.size).toEqual(1); + expect(missing.length).toEqual(0); + expect(failed.length).toEqual(0); + }); + it("marks a setting as missing when its converter returns undefined", () => { // Arrange const { editorSetting, converters } = setupConversionEnvironment(); @@ -39,7 +84,7 @@ describe("convertSettings", () => { const conversionResult: EditorSettingConversionResult = { settings: [ { - settingName: "eslint-setting-a", + settingName: "editor.eslint-setting-a", value: "a", }, ], @@ -56,9 +101,9 @@ describe("convertSettings", () => { expect(converted).toEqual( new Map([ [ - "tslint-setting-a", + "editor.tslint-setting-a", { - settingName: "eslint-setting-a", + settingName: "editor.eslint-setting-a", value: "a", }, ], @@ -76,7 +121,7 @@ function setupConversionEnvironment(conversionResult?: EditorSettingConversionRe function createSampleEditorSetting(): EditorSetting { return { - settingName: "tslint-setting-a", + settingName: "editor.tslint-setting-a", value: "a", }; } diff --git a/src/settings/convertSettings.ts b/src/settings/convertSettings.ts index 59896678d..a506162f0 100644 --- a/src/settings/convertSettings.ts +++ b/src/settings/convertSettings.ts @@ -4,6 +4,8 @@ import { EditorSettingConverter } from "./converter"; import { convertSetting } from "./convertSetting"; import { EditorSetting } from "./types"; +const EDITOR_SETTINGS_PREFIX = "editor."; + export type ConvertSettingsDependencies = { converters: Map; }; @@ -14,18 +16,25 @@ export type SettingConversionResults = { missing: Pick[]; }; -export type EditorConfigurationSettings = Record; +// The entire editor configuration of any keys and values. +export type EditorConfiguration = Record; export const convertSettings = ( dependencies: ConvertSettingsDependencies, - rawEditorSettings: EditorConfigurationSettings, + rawEditorConfiguration: EditorConfiguration, ): SettingConversionResults => { const converted = new Map(); const failed: ConversionError[] = []; const missing: Pick[] = []; - for (const [settingName, value] of Object.entries(rawEditorSettings)) { - const editorSetting = { settingName, value }; + for (const [configurationName, value] of Object.entries(rawEditorConfiguration)) { + // Configurations other than editor settings will be ignored. + // See: https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-tslint-plugin#configuration + if (!configurationName.startsWith(EDITOR_SETTINGS_PREFIX)) { + continue; + } + + const editorSetting = { settingName: configurationName, value }; const conversion = convertSetting(editorSetting, dependencies.converters); if (conversion === undefined) { @@ -40,7 +49,7 @@ export const convertSettings = ( } for (const changes of conversion.settings) { - converted.set(settingName, { ...changes }); + converted.set(configurationName, { ...changes }); } } From fbd54dfffd6b9536846ba3c39b6e9cf4084aeaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 16:05:16 +0100 Subject: [PATCH 35/41] fix: set the already converted setting properly to the conversion result (not the original setting) --- src/settings/convertSettings.test.ts | 2 +- src/settings/convertSettings.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/settings/convertSettings.test.ts b/src/settings/convertSettings.test.ts index c37b2ef64..5c7b47c22 100644 --- a/src/settings/convertSettings.test.ts +++ b/src/settings/convertSettings.test.ts @@ -101,7 +101,7 @@ describe("convertSettings", () => { expect(converted).toEqual( new Map([ [ - "editor.tslint-setting-a", + "editor.eslint-setting-a", { settingName: "editor.eslint-setting-a", value: "a", diff --git a/src/settings/convertSettings.ts b/src/settings/convertSettings.ts index a506162f0..198e248c2 100644 --- a/src/settings/convertSettings.ts +++ b/src/settings/convertSettings.ts @@ -49,7 +49,7 @@ export const convertSettings = ( } for (const changes of conversion.settings) { - converted.set(configurationName, { ...changes }); + converted.set(changes.settingName, { ...changes }); } } From beca462630809bbd1648fb0bbbeaef69ec718915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 17:04:14 +0100 Subject: [PATCH 36/41] feat: use findRawConfiguration to read editor configuration with json comments --- src/cli/main.ts | 9 ++++++--- src/input/findEditorConfiguration.ts | 28 ++++++++-------------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/cli/main.ts b/src/cli/main.ts index 8321dd763..ef895b71f 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -24,7 +24,10 @@ import { WriteConversionResultsDependencies, } from "../creation/writeConversionResults"; import { writeConversionResults as writeEditorConfigConversionResults } from "../creation/writeEditorConfigConversionResults"; -import { findEditorConfiguration } from "../input/findEditorConfiguration"; +import { + findEditorConfiguration, + FindEditorConfigurationDependencies, +} from "../input/findEditorConfiguration"; import { findESLintConfiguration } from "../input/findESLintConfiguration"; import { findOriginalConfigurations, @@ -67,8 +70,8 @@ const findConfigurationDependencies = { importer: boundImporter, }; -const findEditorConfigurationDependencies = { - fileSystem: fsFileSystem, +const findEditorConfigurationDependencies: FindEditorConfigurationDependencies = { + importer: boundImporter, }; const findOriginalConfigurationsDependencies: FindOriginalConfigurationsDependencies = { diff --git a/src/input/findEditorConfiguration.ts b/src/input/findEditorConfiguration.ts index d4449f942..7e1f34fef 100644 --- a/src/input/findEditorConfiguration.ts +++ b/src/input/findEditorConfiguration.ts @@ -1,35 +1,23 @@ -import { FileSystem } from "../adapters/fileSystem"; +import { SansDependencies } from "../binding"; import { EditorConfiguration } from "./editorConfiguration"; +import { findRawConfiguration } from "./findRawConfiguration"; import { DeepPartial } from "./findReportedConfiguration"; +import { importer } from "./importer"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "./vsCodeSettings"; export type FindEditorConfigurationDependencies = { - fileSystem: Pick; + importer: SansDependencies; }; export const findEditorConfiguration = async ( dependencies: FindEditorConfigurationDependencies, config: string | undefined, ): Promise | Error> => { - const rawConfiguration = await readConfiguration( - dependencies.fileSystem, - config || DEFAULT_VSCODE_SETTINGS_PATH, + const filePath = config || DEFAULT_VSCODE_SETTINGS_PATH; + const rawConfiguration = await findRawConfiguration>( + dependencies.importer, + filePath, ); return rawConfiguration; }; - -const readConfiguration = async ( - fileSystem: Pick, - path: string, -): Promise | Error> => { - try { - const fileContents = await fileSystem.readFile(path); - if (fileContents instanceof Error) { - throw new Error(fileContents.message); - } - return JSON.parse(fileContents) as DeepPartial; - } catch (error) { - return error; - } -}; From 88fbe882f06aca0dc87a37c530227f1491a3c09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 17:18:55 +0100 Subject: [PATCH 37/41] test: adjust tests for usage of findRawConfiguration in findEditorConfiguration --- src/input/findEditorConfiguration.test.ts | 42 ++++++++--------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/input/findEditorConfiguration.test.ts b/src/input/findEditorConfiguration.test.ts index 61f16c500..2e6617b8a 100644 --- a/src/input/findEditorConfiguration.test.ts +++ b/src/input/findEditorConfiguration.test.ts @@ -1,40 +1,26 @@ -import { createStubFileSystem, createStubThrowingFileSystem } from "../adapters/fileSystem.stub"; import { findEditorConfiguration, FindEditorConfigurationDependencies, } from "./findEditorConfiguration"; +const stubConfigPath = "temp/"; + +export const createStubImporter = (filePath = "") => + jest.fn().mockReturnValue(Promise.resolve(filePath)); + const createStubDependencies = (overrides: Partial = {}) => ({ - fileSystem: createStubFileSystem(), + importer: createStubImporter(stubConfigPath), ...overrides, }); -const stubConfigPath = "temp/"; - describe("findEditorConfiguration", () => { - it("returns an error when fileSystem returns one", async () => { + it("returns an error when importer returns one", async () => { // Arrange const message = "error"; const dependencies = createStubDependencies({ - fileSystem: createStubFileSystem({ data: new Error(message) }), - }); - - // Act - const result = await findEditorConfiguration(dependencies, stubConfigPath); - - // Assert - expect(result).toEqual( - expect.objectContaining({ - message, - }), - ); - }); - - it("returns an error when fileSystem throws one", async () => { - // Arrange - const message = "error"; - const dependencies = createStubDependencies({ - fileSystem: createStubThrowingFileSystem({ err: message }), + importer: async () => { + throw new Error(message); + }, }); // Act @@ -57,7 +43,7 @@ describe("findEditorConfiguration", () => { await findEditorConfiguration(dependencies, configPath); // Assert - expect(dependencies.fileSystem.readFile).toHaveBeenLastCalledWith(configPath); + expect(dependencies.importer).toHaveBeenLastCalledWith(configPath); }); it("defaults to VS Code editor settings path when config path isn't provided", async () => { @@ -68,7 +54,7 @@ describe("findEditorConfiguration", () => { await findEditorConfiguration(dependencies, undefined); // Assert - expect(dependencies.fileSystem.readFile).toHaveBeenLastCalledWith(".vscode/settings.json"); + expect(dependencies.importer).toHaveBeenLastCalledWith(".vscode/settings.json"); }); it("parses object from configuration path when read successfully", async () => { @@ -80,9 +66,9 @@ describe("findEditorConfiguration", () => { "source.organizeImports": false, }, }; - const data = JSON.stringify(originalConfig); + const dependencies = createStubDependencies({ - fileSystem: createStubFileSystem({ data }), + importer: async () => originalConfig, }); // Act From 53f37d4abab38a472fd95561fa23c13641fcd518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 18:05:43 +0100 Subject: [PATCH 38/41] refactor: specify naming, every "setting" to be an "editorSetting" --- jest.config.js | 2 +- src/cli/main.ts | 17 +++--- src/conversion/conversionResults.stubs.ts | 6 +-- src/conversion/convertEditorConfig.test.ts | 12 ++--- src/conversion/convertEditorConfig.ts | 12 +++-- ...writeEditorConfigConversionResults.test.ts | 12 ++--- .../writeEditorConfigConversionResults.ts | 8 +-- .../convertEditorSetting.test.ts} | 18 +++---- .../convertEditorSetting.ts} | 4 +- .../convertEditorSettings.test.ts} | 44 ++++++++------- .../convertEditorSettings.ts} | 26 ++++----- src/{settings => editorSettings}/converter.ts | 2 +- .../converters/editor-code-actions-on-save.ts | 4 +- .../tests/editor-code-actions-on-save.test.ts | 18 +++---- .../editorSettingsConverters.ts} | 2 +- src/{settings => editorSettings}/types.ts | 2 +- src/errors/conversionError.ts | 4 +- ...ortEditorSettingConversionResults.test.ts} | 54 +++++++++---------- .../reportEditorSettingConversionResults.ts | 39 ++++++++++++++ src/reporting/reportOutputs.ts | 4 +- .../reportSettingConversionResults.ts | 38 ------------- src/rules/converters/no-explicit-any.ts | 11 ---- 22 files changed, 170 insertions(+), 169 deletions(-) rename src/{settings/convertSetting.test.ts => editorSettings/convertEditorSetting.test.ts} (77%) rename src/{settings/convertSetting.ts => editorSettings/convertEditorSetting.ts} (81%) rename src/{settings/convertSettings.test.ts => editorSettings/convertEditorSettings.test.ts} (70%) rename src/{settings/convertSettings.ts => editorSettings/convertEditorSettings.ts} (63%) rename src/{settings => editorSettings}/converter.ts (96%) rename src/{settings => editorSettings}/converters/editor-code-actions-on-save.ts (84%) rename src/{settings => editorSettings}/converters/tests/editor-code-actions-on-save.test.ts (75%) rename src/{settings/settingsConverters.ts => editorSettings/editorSettingsConverters.ts} (84%) rename src/{settings => editorSettings}/types.ts (61%) rename src/reporting/{reportSettingConversionResults.test.ts => reportEditorSettingConversionResults.test.ts} (62%) create mode 100644 src/reporting/reportEditorSettingConversionResults.ts delete mode 100644 src/reporting/reportSettingConversionResults.ts delete mode 100644 src/rules/converters/no-explicit-any.ts diff --git a/jest.config.js b/jest.config.js index 5da25e8ba..1e574609c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,7 +5,7 @@ module.exports = { "!./src/**/*.stubs.ts", "!./src/adapters/*.ts", "!./src/rules/rulesConverters.ts", - "!./src/settings/settingsConverters.ts", + "!./src/editorSettings/editorSettingsConverters.ts", "!./src/rules/mergers.ts", "!./src/cli/main.ts", ], diff --git a/src/cli/main.ts b/src/cli/main.ts index ef895b71f..b3adcd29b 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -24,6 +24,11 @@ import { WriteConversionResultsDependencies, } from "../creation/writeConversionResults"; import { writeConversionResults as writeEditorConfigConversionResults } from "../creation/writeEditorConfigConversionResults"; +import { + convertEditorSettings, + ConvertEditorSettingsDependencies, +} from "../editorSettings/convertEditorSettings"; +import { editorSettingsConverters } from "../editorSettings/editorSettingsConverters"; import { findEditorConfiguration, FindEditorConfigurationDependencies, @@ -40,12 +45,10 @@ import { importer, ImporterDependencies } from "../input/importer"; import { mergeLintConfigurations } from "../input/mergeLintConfigurations"; import { ReportConversionResultsDependencies } from "../reporting/dependencies"; import { reportConversionResults } from "../reporting/reportConversionResults"; -import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; +import { reportEditorSettingConversionResults } from "../reporting/reportEditorSettingConversionResults"; import { convertRules, ConvertRulesDependencies } from "../rules/convertRules"; import { mergers } from "../rules/mergers"; import { rulesConverters } from "../rules/rulesConverters"; -import { convertSettings, ConvertSettingsDependencies } from "../settings/convertSettings"; -import { settingsConverters } from "../settings/settingsConverters"; import { runCli, RunCliDependencies } from "./runCli"; const convertRulesDependencies: ConvertRulesDependencies = { @@ -53,8 +56,8 @@ const convertRulesDependencies: ConvertRulesDependencies = { mergers, }; -const convertSettingsDependencies: ConvertSettingsDependencies = { - converters: settingsConverters, +const convertEditorSettingsDependencies: ConvertEditorSettingsDependencies = { + converters: editorSettingsConverters, }; const nativeImporterDependencies: ImporterDependencies = { @@ -100,10 +103,10 @@ const writeConversionResultsDependencies: WriteConversionResultsDependencies = { }; const convertEditorConfigDependencies: ConvertEditorConfigDependencies = { - convertSettings: bind(convertSettings, convertSettingsDependencies), findEditorConfiguration: bind(findEditorConfiguration, findEditorConfigurationDependencies), + convertEditorSettings: bind(convertEditorSettings, convertEditorSettingsDependencies), reportConversionResults: bind( - reportSettingConversionResults, + reportEditorSettingConversionResults, reportConversionResultsDependencies, ), writeConversionResults: bind( diff --git a/src/conversion/conversionResults.stubs.ts b/src/conversion/conversionResults.stubs.ts index e71c3a675..b3a6ffdfc 100644 --- a/src/conversion/conversionResults.stubs.ts +++ b/src/conversion/conversionResults.stubs.ts @@ -1,5 +1,5 @@ +import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings"; import { RuleConversionResults } from "../rules/convertRules"; -import { SettingConversionResults } from "../settings/convertSettings"; export const createEmptyConversionResults = ( overrides: Partial = {}, @@ -12,8 +12,8 @@ export const createEmptyConversionResults = ( }); export const createEmptySettingConversionResults = ( - overrides: Partial = {}, -): SettingConversionResults => ({ + overrides: Partial = {}, +): EditorSettingConversionResults => ({ converted: new Map(), failed: [], missing: [], diff --git a/src/conversion/convertEditorConfig.test.ts b/src/conversion/convertEditorConfig.test.ts index a5f3fed78..c6493256f 100644 --- a/src/conversion/convertEditorConfig.test.ts +++ b/src/conversion/convertEditorConfig.test.ts @@ -1,4 +1,4 @@ -import { EditorSetting } from "../settings/types"; +import { EditorSetting } from "../editorSettings/types"; import { FailedResult, ResultStatus } from "../types"; import { createEmptySettingConversionResults } from "./conversionResults.stubs"; import { convertEditorConfig, ConvertEditorConfigDependencies } from "./convertEditorConfig"; @@ -11,7 +11,7 @@ const stubSettings = { const createStubDependencies = ( overrides: Partial = {}, ): ConvertEditorConfigDependencies => ({ - convertSettings: jest.fn(), + convertEditorSettings: jest.fn(), findEditorConfiguration: jest.fn().mockResolvedValue({}), reportConversionResults: jest.fn(), writeConversionResults: jest.fn().mockReturnValue(Promise.resolve()), @@ -73,7 +73,7 @@ describe("convertEditorConfig", () => { await convertEditorConfig(dependencies, stubSettings); // Assert - expect(dependencies.convertSettings).toHaveBeenCalledWith(originalConfig); + expect(dependencies.convertEditorSettings).toHaveBeenCalledWith(originalConfig); }); it("reports conversion results when settings are converted successfully", async () => { @@ -81,9 +81,9 @@ describe("convertEditorConfig", () => { const conversionResults = createEmptySettingConversionResults({ converted: new Map([ [ - "tslint-setting-one", + "tslint-editor-setting-one", { - settingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", value: 42, }, ], @@ -91,7 +91,7 @@ describe("convertEditorConfig", () => { }); const dependencies = createStubDependencies({ - convertSettings: jest.fn().mockReturnValue(conversionResults), + convertEditorSettings: jest.fn().mockReturnValue(conversionResults), }); // Act diff --git a/src/conversion/convertEditorConfig.ts b/src/conversion/convertEditorConfig.ts index 459046c7f..2d78ba630 100644 --- a/src/conversion/convertEditorConfig.ts +++ b/src/conversion/convertEditorConfig.ts @@ -1,15 +1,15 @@ import { SansDependencies } from "../binding"; import { writeConversionResults } from "../creation/writeEditorConfigConversionResults"; +import { convertEditorSettings } from "../editorSettings/convertEditorSettings"; import { findEditorConfiguration } from "../input/findEditorConfiguration"; import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings"; -import { reportSettingConversionResults } from "../reporting/reportSettingConversionResults"; -import { convertSettings } from "../settings/convertSettings"; +import { reportEditorSettingConversionResults } from "../reporting/reportEditorSettingConversionResults"; import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types"; export type ConvertEditorConfigDependencies = { - convertSettings: SansDependencies; + convertEditorSettings: SansDependencies; findEditorConfiguration: SansDependencies; - reportConversionResults: SansDependencies; + reportConversionResults: SansDependencies; writeConversionResults: SansDependencies; }; @@ -31,7 +31,9 @@ export const convertEditorConfig = async ( }; } - const settingConversionResults = dependencies.convertSettings(originalEditorConfiguration); + const settingConversionResults = dependencies.convertEditorSettings( + originalEditorConfiguration, + ); const outputPath = editorConfigPath; const fileWriteError = await dependencies.writeConversionResults( diff --git a/src/creation/writeEditorConfigConversionResults.test.ts b/src/creation/writeEditorConfigConversionResults.test.ts index c66a1a6e6..02e36414b 100644 --- a/src/creation/writeEditorConfigConversionResults.test.ts +++ b/src/creation/writeEditorConfigConversionResults.test.ts @@ -1,9 +1,9 @@ import { createStubFileSystem } from "../adapters/fileSystem.stub"; import { createEmptySettingConversionResults } from "../conversion/conversionResults.stubs"; +import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings"; +import { EditorSetting } from "../editorSettings/types"; import { EditorConfiguration } from "../input/editorConfiguration"; import { DeepPartial } from "../input/findReportedConfiguration"; -import { SettingConversionResults } from "../settings/convertSettings"; -import { EditorSetting } from "../settings/types"; import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput"; import { writeConversionResults, @@ -51,14 +51,14 @@ describe("writeConversionResults", () => { [ "eslint-setting-b", { - settingName: "eslint-setting-b", + editorSettingName: "eslint-setting-b", value: 42, }, ], [ "eslint-setting-a", { - settingName: "eslint-setting-a", + editorSettingName: "eslint-setting-a", value: 4711, }, ], @@ -90,7 +90,7 @@ describe("writeConversionResults", () => { function setupConversionEnvironment( overrides: { - conversionResults?: SettingConversionResults; + conversionResults?: EditorSettingConversionResults; originalConfig?: DeepPartial; } = {}, ) { @@ -107,7 +107,7 @@ function setupConversionEnvironment( [ "tslint-setting-one", { - settingName: "tslint-setting-one", + editorSettingName: "tslint-setting-one", value: 42, }, ], diff --git a/src/creation/writeEditorConfigConversionResults.ts b/src/creation/writeEditorConfigConversionResults.ts index 349186cc3..0d9deba50 100644 --- a/src/creation/writeEditorConfigConversionResults.ts +++ b/src/creation/writeEditorConfigConversionResults.ts @@ -1,8 +1,8 @@ import { FileSystem } from "../adapters/fileSystem"; +import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings"; import { EditorConfiguration } from "../input/editorConfiguration"; -import { SettingConversionResults } from "../settings/convertSettings"; -import { formatOutput } from "./formatting/formatOutput"; import { DeepPartial } from "../input/findReportedConfiguration"; +import { formatOutput } from "./formatting/formatOutput"; export type WriteConversionResultsDependencies = { fileSystem: Pick; @@ -11,7 +11,7 @@ export type WriteConversionResultsDependencies = { export const writeConversionResults = async ( dependencies: WriteConversionResultsDependencies, outputPath: string, - conversionResults: SettingConversionResults, + conversionResults: EditorSettingConversionResults, originalConfiguration: DeepPartial, ) => { const output = { @@ -22,7 +22,7 @@ export const writeConversionResults = async ( return await dependencies.fileSystem.writeFile(outputPath, formatOutput(outputPath, output)); }; -export const formatConvertedSettings = (conversionResults: SettingConversionResults) => { +export const formatConvertedSettings = (conversionResults: EditorSettingConversionResults) => { const output: { [i: string]: string | any[] } = {}; const sortedEntries = Array.from(conversionResults.converted).sort(([nameA], [nameB]) => nameA.localeCompare(nameB), diff --git a/src/settings/convertSetting.test.ts b/src/editorSettings/convertEditorSetting.test.ts similarity index 77% rename from src/settings/convertSetting.test.ts rename to src/editorSettings/convertEditorSetting.test.ts index 819e7c75c..6743c8044 100644 --- a/src/settings/convertSetting.test.ts +++ b/src/editorSettings/convertEditorSetting.test.ts @@ -1,17 +1,17 @@ import { ConversionError } from "../errors/conversionError"; +import { convertEditorSetting } from "./convertEditorSetting"; import { EditorSettingConverter } from "./converter"; -import { convertSetting } from "./convertSetting"; import { EditorSetting } from "./types"; -describe("convertSetting", () => { +describe("convertEditorSetting", () => { it("returns undefined when no converter exists for a setting", () => { // Arrange const converters = new Map(); // Act - const result = convertSetting( + const result = convertEditorSetting( { - settingName: "tslint-setting", + editorSettingName: "tslint-setting", value: "any value", }, converters, @@ -26,7 +26,7 @@ describe("convertSetting", () => { const converted = { settings: [ { - settingName: "eslint-setting", + editorSettingName: "eslint-setting", value: "new value", }, ], @@ -36,9 +36,9 @@ describe("convertSetting", () => { ]); // Act - const result = convertSetting( + const result = convertEditorSetting( { - settingName: "tslint-setting", + editorSettingName: "tslint-setting", value: "existing value", }, converters, @@ -60,12 +60,12 @@ describe("convertSetting", () => { ], ]); const tsLintSetting: EditorSetting = { - settingName: "tslint-setting", + editorSettingName: "tslint-setting", value: "existing value", }; // Act - const result = convertSetting(tsLintSetting, converters); + const result = convertEditorSetting(tsLintSetting, converters); // Assert expect(result).toEqual(ConversionError.forSettingError(error, tsLintSetting)); diff --git a/src/settings/convertSetting.ts b/src/editorSettings/convertEditorSetting.ts similarity index 81% rename from src/settings/convertSetting.ts rename to src/editorSettings/convertEditorSetting.ts index 4f62c6bb7..0843a51c9 100644 --- a/src/settings/convertSetting.ts +++ b/src/editorSettings/convertEditorSetting.ts @@ -2,11 +2,11 @@ import { ConversionError } from "../errors/conversionError"; import { EditorSettingConverter } from "./converter"; import { EditorSetting } from "./types"; -export const convertSetting = ( +export const convertEditorSetting = ( editorSetting: EditorSetting, converters: Map, ) => { - const converter = converters.get(editorSetting.settingName); + const converter = converters.get(editorSetting.editorSettingName); if (converter === undefined) { return undefined; } diff --git a/src/settings/convertSettings.test.ts b/src/editorSettings/convertEditorSettings.test.ts similarity index 70% rename from src/settings/convertSettings.test.ts rename to src/editorSettings/convertEditorSettings.test.ts index 5c7b47c22..22fde39b1 100644 --- a/src/settings/convertSettings.test.ts +++ b/src/editorSettings/convertEditorSettings.test.ts @@ -1,9 +1,9 @@ import { ConversionError } from "../errors/conversionError"; -import { convertSettings } from "./convertSettings"; +import { convertEditorSettings } from "./convertEditorSettings"; +import { EditorSettingConversionResult, EditorSettingConverter } from "./converter"; import { EditorSetting } from "./types"; -import { EditorSettingConverter, EditorSettingConversionResult } from "./converter"; -describe("convertSettings", () => { +describe("convertEditorSettings", () => { it("skips entire conversion if none of the configurations is an editor setting", () => { // Arrange const { converters } = setupConversionEnvironment(); @@ -13,7 +13,10 @@ describe("convertSettings", () => { }; // Act - const { converted, missing, failed } = convertSettings({ converters }, editorConfiguration); + const { converted, missing, failed } = convertEditorSettings( + { converters }, + editorConfiguration, + ); // Assert expect(converted.size).toEqual(0); @@ -26,7 +29,7 @@ describe("convertSettings", () => { const conversionResult: EditorSettingConversionResult = { settings: [ { - settingName: "editor.eslint-setting-a", + editorSettingName: "editor.eslint-setting-a", value: "a", }, ], @@ -36,12 +39,15 @@ describe("convertSettings", () => { const editorConfiguration = { notAnEditorSetting: "a", - [editorSetting.settingName]: editorSetting, + [editorSetting.editorSettingName]: editorSetting, notAnEditorSettingEither: "b", }; // Act - const { converted, missing, failed } = convertSettings({ converters }, editorConfiguration); + const { converted, missing, failed } = convertEditorSettings( + { converters }, + editorConfiguration, + ); // Assert expect(converted.size).toEqual(1); @@ -54,25 +60,25 @@ describe("convertSettings", () => { const { editorSetting, converters } = setupConversionEnvironment(); // Act - const { missing } = convertSettings( + const { missing } = convertEditorSettings( { converters }, - { [editorSetting.settingName]: editorSetting }, + { [editorSetting.editorSettingName]: editorSetting }, ); // Assert - expect(missing).toEqual([{ settingName: editorSetting.settingName }]); + expect(missing).toEqual([{ editorSettingName: editorSetting.editorSettingName }]); }); it("marks a conversion as failed when returned a conversion error", () => { // Arrange const { editorSetting, converters } = setupConversionEnvironment(); const conversionError = ConversionError.forSettingError(new Error(), editorSetting); - converters.set(editorSetting.settingName, () => conversionError); + converters.set(editorSetting.editorSettingName, () => conversionError); // Act - const { failed } = convertSettings( + const { failed } = convertEditorSettings( { converters }, - { [editorSetting.settingName]: editorSetting }, + { [editorSetting.editorSettingName]: editorSetting }, ); // Assert @@ -84,7 +90,7 @@ describe("convertSettings", () => { const conversionResult: EditorSettingConversionResult = { settings: [ { - settingName: "editor.eslint-setting-a", + editorSettingName: "editor.eslint-setting-a", value: "a", }, ], @@ -92,9 +98,9 @@ describe("convertSettings", () => { const { editorSetting, converters } = setupConversionEnvironment(conversionResult); // Act - const { converted } = convertSettings( + const { converted } = convertEditorSettings( { converters }, - { [editorSetting.settingName]: editorSetting.value }, + { [editorSetting.editorSettingName]: editorSetting.value }, ); // Assert @@ -103,7 +109,7 @@ describe("convertSettings", () => { [ "editor.eslint-setting-a", { - settingName: "editor.eslint-setting-a", + editorSettingName: "editor.eslint-setting-a", value: "a", }, ], @@ -121,7 +127,7 @@ function setupConversionEnvironment(conversionResult?: EditorSettingConversionRe function createSampleEditorSetting(): EditorSetting { return { - settingName: "editor.tslint-setting-a", + editorSettingName: "editor.tslint-setting-a", value: "a", }; } @@ -133,7 +139,7 @@ function createConverters( const converters = new Map(); if (conversionResult !== undefined) { - converters.set(tslintSetting.settingName, () => conversionResult); + converters.set(tslintSetting.editorSettingName, () => conversionResult); } return converters; diff --git a/src/settings/convertSettings.ts b/src/editorSettings/convertEditorSettings.ts similarity index 63% rename from src/settings/convertSettings.ts rename to src/editorSettings/convertEditorSettings.ts index 198e248c2..809adaec8 100644 --- a/src/settings/convertSettings.ts +++ b/src/editorSettings/convertEditorSettings.ts @@ -1,31 +1,31 @@ import { ConversionError } from "../errors/conversionError"; import { ErrorSummary } from "../errors/errorSummary"; +import { convertEditorSetting } from "./convertEditorSetting"; import { EditorSettingConverter } from "./converter"; -import { convertSetting } from "./convertSetting"; import { EditorSetting } from "./types"; const EDITOR_SETTINGS_PREFIX = "editor."; -export type ConvertSettingsDependencies = { +export type ConvertEditorSettingsDependencies = { converters: Map; }; -export type SettingConversionResults = { +export type EditorSettingConversionResults = { converted: Map; failed: ErrorSummary[]; - missing: Pick[]; + missing: Pick[]; }; // The entire editor configuration of any keys and values. export type EditorConfiguration = Record; -export const convertSettings = ( - dependencies: ConvertSettingsDependencies, +export const convertEditorSettings = ( + dependencies: ConvertEditorSettingsDependencies, rawEditorConfiguration: EditorConfiguration, -): SettingConversionResults => { +): EditorSettingConversionResults => { const converted = new Map(); const failed: ConversionError[] = []; - const missing: Pick[] = []; + const missing: Pick[] = []; for (const [configurationName, value] of Object.entries(rawEditorConfiguration)) { // Configurations other than editor settings will be ignored. @@ -34,12 +34,12 @@ export const convertSettings = ( continue; } - const editorSetting = { settingName: configurationName, value }; - const conversion = convertSetting(editorSetting, dependencies.converters); + const editorSetting = { editorSettingName: configurationName, value }; + const conversion = convertEditorSetting(editorSetting, dependencies.converters); if (conversion === undefined) { - const { settingName } = editorSetting; - missing.push({ settingName }); + const { editorSettingName } = editorSetting; + missing.push({ editorSettingName }); continue; } @@ -49,7 +49,7 @@ export const convertSettings = ( } for (const changes of conversion.settings) { - converted.set(changes.settingName, { ...changes }); + converted.set(changes.editorSettingName, { ...changes }); } } diff --git a/src/settings/converter.ts b/src/editorSettings/converter.ts similarity index 96% rename from src/settings/converter.ts rename to src/editorSettings/converter.ts index a0caf0f80..b3121aa03 100644 --- a/src/settings/converter.ts +++ b/src/editorSettings/converter.ts @@ -30,5 +30,5 @@ export type ConvertedEditorSettingChanges = { /** * Equivalent ESLint editor setting name that should be enabled. */ - settingName: string; + editorSettingName: string; }; diff --git a/src/settings/converters/editor-code-actions-on-save.ts b/src/editorSettings/converters/editor-code-actions-on-save.ts similarity index 84% rename from src/settings/converters/editor-code-actions-on-save.ts rename to src/editorSettings/converters/editor-code-actions-on-save.ts index ef0fb6351..e8f114b5d 100644 --- a/src/settings/converters/editor-code-actions-on-save.ts +++ b/src/editorSettings/converters/editor-code-actions-on-save.ts @@ -12,11 +12,11 @@ export const convertEditorCodeActionsOnSave: EditorSettingConverter = originalCo return { settings: [ { - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: codeActionsOnSaveWithoutReplacedProperties, }, { - settingName: "eslint.autoFixOnSave", + editorSettingName: "eslint.autoFixOnSave", value: originalSourceFixAllTsLint, }, ], diff --git a/src/settings/converters/tests/editor-code-actions-on-save.test.ts b/src/editorSettings/converters/tests/editor-code-actions-on-save.test.ts similarity index 75% rename from src/settings/converters/tests/editor-code-actions-on-save.test.ts rename to src/editorSettings/converters/tests/editor-code-actions-on-save.test.ts index 09231f2ea..425de1a6e 100644 --- a/src/settings/converters/tests/editor-code-actions-on-save.test.ts +++ b/src/editorSettings/converters/tests/editor-code-actions-on-save.test.ts @@ -3,7 +3,7 @@ import { convertEditorCodeActionsOnSave } from "../editor-code-actions-on-save"; describe(convertEditorCodeActionsOnSave, () => { test("conversion of 'source.fixAll.tslint' when value is true", () => { const result = convertEditorCodeActionsOnSave({ - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: { "source.fixAll.tslint": true, }, @@ -12,11 +12,11 @@ describe(convertEditorCodeActionsOnSave, () => { expect(result).toEqual({ settings: [ { - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: {}, }, { - settingName: "eslint.autoFixOnSave", + editorSettingName: "eslint.autoFixOnSave", value: true, }, ], @@ -25,7 +25,7 @@ describe(convertEditorCodeActionsOnSave, () => { test("conversion of 'source.fixAll.tslint' when value is false", () => { const result = convertEditorCodeActionsOnSave({ - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: { "source.fixAll.tslint": false, }, @@ -34,11 +34,11 @@ describe(convertEditorCodeActionsOnSave, () => { expect(result).toEqual({ settings: [ { - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: {}, }, { - settingName: "eslint.autoFixOnSave", + editorSettingName: "eslint.autoFixOnSave", value: false, }, ], @@ -47,7 +47,7 @@ describe(convertEditorCodeActionsOnSave, () => { test("conversion of 'source.fixAll.tslint' without touching any other 'editor.codeActionsOnSave'", () => { const result = convertEditorCodeActionsOnSave({ - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: { "one-property": 42, "source.fixAll.tslint": true, @@ -58,14 +58,14 @@ describe(convertEditorCodeActionsOnSave, () => { expect(result).toEqual({ settings: [ { - settingName: "editor.codeActionsOnSave", + editorSettingName: "editor.codeActionsOnSave", value: { "one-property": 42, "another-property": "foo", }, }, { - settingName: "eslint.autoFixOnSave", + editorSettingName: "eslint.autoFixOnSave", value: true, }, ], diff --git a/src/settings/settingsConverters.ts b/src/editorSettings/editorSettingsConverters.ts similarity index 84% rename from src/settings/settingsConverters.ts rename to src/editorSettings/editorSettingsConverters.ts index 76c9b9095..ec36c0e3a 100644 --- a/src/settings/settingsConverters.ts +++ b/src/editorSettings/editorSettingsConverters.ts @@ -3,6 +3,6 @@ import { convertEditorCodeActionsOnSave } from "./converters/editor-code-actions /** * Keys TSLint property names in editor settings to their ESLint editor settings converters. */ -export const settingsConverters = new Map([ +export const editorSettingsConverters = new Map([ ["editor.codeActionsOnSave", convertEditorCodeActionsOnSave], ]); diff --git a/src/settings/types.ts b/src/editorSettings/types.ts similarity index 61% rename from src/settings/types.ts rename to src/editorSettings/types.ts index 50138d519..2c8ff4d54 100644 --- a/src/settings/types.ts +++ b/src/editorSettings/types.ts @@ -1,4 +1,4 @@ export type EditorSetting = { - settingName: string; + editorSettingName: string; value: any; }; diff --git a/src/errors/conversionError.ts b/src/errors/conversionError.ts index 4716a095d..c2766c8f7 100644 --- a/src/errors/conversionError.ts +++ b/src/errors/conversionError.ts @@ -1,8 +1,8 @@ import { EOL } from "os"; +import { EditorSetting } from "../editorSettings/types"; import { TSLintRuleOptions } from "../rules/types"; import { ErrorSummary } from "./errorSummary"; -import { EditorSetting } from "../settings/types"; export class ConversionError implements ErrorSummary { private constructor(private readonly summary: string) {} @@ -24,7 +24,7 @@ export class ConversionError implements ErrorSummary { public static forSettingError(error: Error, editorSetting: EditorSetting) { return new ConversionError( - `${editorSetting.settingName} threw an error during conversion: ${error.stack}${EOL}`, + `${editorSetting.editorSettingName} threw an error during conversion: ${error.stack}${EOL}`, ); } diff --git a/src/reporting/reportSettingConversionResults.test.ts b/src/reporting/reportEditorSettingConversionResults.test.ts similarity index 62% rename from src/reporting/reportSettingConversionResults.test.ts rename to src/reporting/reportEditorSettingConversionResults.test.ts index 2fb953b5a..c16c65fd0 100644 --- a/src/reporting/reportSettingConversionResults.test.ts +++ b/src/reporting/reportEditorSettingConversionResults.test.ts @@ -2,18 +2,18 @@ import { EOL } from "os"; import { createStubLogger, expectEqualWrites } from "../adapters/logger.stubs"; import { createEmptySettingConversionResults } from "../conversion/conversionResults.stubs"; -import { EditorSetting } from "../settings/types"; -import { reportSettingConversionResults } from "./reportSettingConversionResults"; +import { EditorSetting } from "../editorSettings/types"; +import { reportEditorSettingConversionResults } from "./reportEditorSettingConversionResults"; -describe("reportSettingConversionResults", () => { - it("logs a successful conversion when there is one converted setting", () => { +describe("reportEditorSettingConversionResults", () => { + it("logs a successful conversion when there is one converted editor setting", () => { // Arrange const conversionResults = createEmptySettingConversionResults({ converted: new Map([ [ - "tslint-setting-one", + "tslint-editor-setting-one", { - settingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", value: 42, }, ], @@ -23,12 +23,12 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( logger.stdout.write, - `✨ 1 setting replaced with its ESLint equivalent. ✨${EOL}`, + `✨ 1 editor setting replaced with its ESLint equivalent. ✨${EOL}`, ); }); @@ -37,16 +37,16 @@ describe("reportSettingConversionResults", () => { const conversionResults = createEmptySettingConversionResults({ converted: new Map([ [ - "tslint-setting-one", + "tslint-editor-setting-one", { - settingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", value: 42, }, ], [ - "tslint-setting-two", + "tslint-editor-setting-two", { - settingName: "tslint-setting-two", + editorSettingName: "tslint-editor-setting-two", value: 4711, }, ], @@ -56,12 +56,12 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( logger.stdout.write, - `✨ 2 settings replaced with their ESLint equivalents. ✨${EOL}`, + `✨ 2 editor settings replaced with their ESLint equivalents. ✨${EOL}`, ); }); @@ -74,7 +74,7 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( @@ -93,7 +93,7 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( @@ -103,12 +103,12 @@ describe("reportSettingConversionResults", () => { ); }); - it("logs a missing setting when there is a missing setting", () => { + it("logs a missing editor setting when there is a missing setting", () => { // Arrange const conversionResults = createEmptySettingConversionResults({ missing: [ { - settingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", }, ], }); @@ -116,16 +116,16 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( logger.stdout.write, - "👀 1 setting does not yet have an ESLint equivalent (see generated log file). 👀", + "👀 1 editor setting does not yet have an ESLint equivalent (see generated log file). 👀", ); expectEqualWrites( logger.info.write, - "tslint-setting-one does not yet have an ESLint equivalent.", + "tslint-editor-setting-one does not yet have an ESLint equivalent.", ); }); @@ -134,10 +134,10 @@ describe("reportSettingConversionResults", () => { const conversionResults = createEmptySettingConversionResults({ missing: [ { - settingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", }, { - settingName: "tslint-setting-two", + editorSettingName: "tslint-editor-setting-two", }, ], }); @@ -145,17 +145,17 @@ describe("reportSettingConversionResults", () => { const logger = createStubLogger(); // Act - reportSettingConversionResults({ logger }, conversionResults); + reportEditorSettingConversionResults({ logger }, conversionResults); // Assert expectEqualWrites( logger.stdout.write, - "👀 2 settings do not yet have ESLint equivalents (see generated log file). 👀", + "👀 2 editor settings do not yet have ESLint equivalents (see generated log file). 👀", ); expectEqualWrites( logger.info.write, - "tslint-setting-one does not yet have an ESLint equivalent.", - "tslint-setting-two does not yet have an ESLint equivalent.", + "tslint-editor-setting-one does not yet have an ESLint equivalent.", + "tslint-editor-setting-two does not yet have an ESLint equivalent.", ); }); }); diff --git a/src/reporting/reportEditorSettingConversionResults.ts b/src/reporting/reportEditorSettingConversionResults.ts new file mode 100644 index 000000000..12ebf1a29 --- /dev/null +++ b/src/reporting/reportEditorSettingConversionResults.ts @@ -0,0 +1,39 @@ +import { EOL } from "os"; + +import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings"; +import { EditorSetting } from "../editorSettings/types"; +import { ReportConversionResultsDependencies } from "./dependencies"; +import { + logFailedConversions, + logMissingConversionTarget, + logSuccessfulConversions, +} from "./reportOutputs"; + +export const reportEditorSettingConversionResults = ( + dependencies: ReportConversionResultsDependencies, + editorSettingConversionResults: EditorSettingConversionResults, +) => { + if (editorSettingConversionResults.converted.size !== 0) { + logSuccessfulConversions( + "editor setting", + editorSettingConversionResults.converted, + dependencies.logger, + ); + } + + if (editorSettingConversionResults.failed.length !== 0) { + logFailedConversions(editorSettingConversionResults.failed, dependencies.logger); + } + + if (editorSettingConversionResults.missing.length !== 0) { + const missingEditorSettingOutputMapping = ( + editorSetting: Pick, + ) => `${editorSetting.editorSettingName} does not yet have an ESLint equivalent.${EOL}`; + logMissingConversionTarget( + "editor setting", + missingEditorSettingOutputMapping, + editorSettingConversionResults.missing, + dependencies.logger, + ); + } +}; diff --git a/src/reporting/reportOutputs.ts b/src/reporting/reportOutputs.ts index ce59760c1..67af19d65 100644 --- a/src/reporting/reportOutputs.ts +++ b/src/reporting/reportOutputs.ts @@ -2,11 +2,11 @@ import chalk from "chalk"; import { EOL } from "os"; import { Logger } from "../adapters/logger"; +import { EditorSetting } from "../editorSettings/types"; import { ErrorSummary } from "../errors/errorSummary"; import { ESLintRuleOptions } from "../rules/types"; -import { EditorSetting } from "../settings/types"; -export type EditorSettingEntry = Pick; +export type EditorSettingEntry = Pick; export const logSuccessfulConversions = ( conversionTypeName: string, diff --git a/src/reporting/reportSettingConversionResults.ts b/src/reporting/reportSettingConversionResults.ts deleted file mode 100644 index 3ec74c076..000000000 --- a/src/reporting/reportSettingConversionResults.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { EOL } from "os"; - -import { SettingConversionResults } from "../settings/convertSettings"; -import { EditorSetting } from "../settings/types"; -import { ReportConversionResultsDependencies } from "./dependencies"; -import { - logFailedConversions, - logMissingConversionTarget, - logSuccessfulConversions, -} from "./reportOutputs"; - -export const reportSettingConversionResults = ( - dependencies: ReportConversionResultsDependencies, - settingConversionResults: SettingConversionResults, -) => { - if (settingConversionResults.converted.size !== 0) { - logSuccessfulConversions( - "setting", - settingConversionResults.converted, - dependencies.logger, - ); - } - - if (settingConversionResults.failed.length !== 0) { - logFailedConversions(settingConversionResults.failed, dependencies.logger); - } - - if (settingConversionResults.missing.length !== 0) { - const missingSettingOutputMapping = (setting: Pick) => - `${setting.settingName} does not yet have an ESLint equivalent.${EOL}`; - logMissingConversionTarget( - "setting", - missingSettingOutputMapping, - settingConversionResults.missing, - dependencies.logger, - ); - } -}; diff --git a/src/rules/converters/no-explicit-any.ts b/src/rules/converters/no-explicit-any.ts deleted file mode 100644 index 0a4af7e10..000000000 --- a/src/rules/converters/no-explicit-any.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { RuleConverter } from "../converter"; - -export const convertNoExplicitAny: RuleConverter = () => { - return { - rules: [ - { - ruleName: "@typescript-eslint/no-explicit-any", - }, - ], - }; -}; From db860ffee5aaf2f945b2d4ecfa412edccebdf682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 18:34:28 +0100 Subject: [PATCH 39/41] style: format imports --- src/cli/runCli.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cli/runCli.ts b/src/cli/runCli.ts index 36d140a9a..0a1cba644 100644 --- a/src/cli/runCli.ts +++ b/src/cli/runCli.ts @@ -1,6 +1,7 @@ import chalk from "chalk"; import { Command } from "commander"; import { EOL } from "os"; + import { version } from "../../package.json"; import { Logger } from "../adapters/logger"; import { SansDependencies } from "../binding"; From 8733b0db09eb659ea1f921f69935d7168e5ca260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 18:40:04 +0100 Subject: [PATCH 40/41] style: change sample name of editor-setting in tests --- .../writeEditorConfigConversionResults.test.ts | 4 ++-- src/editorSettings/convertEditorSetting.test.ts | 10 +++++----- src/editorSettings/convertEditorSettings.test.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/creation/writeEditorConfigConversionResults.test.ts b/src/creation/writeEditorConfigConversionResults.test.ts index 02e36414b..4a09d8ecb 100644 --- a/src/creation/writeEditorConfigConversionResults.test.ts +++ b/src/creation/writeEditorConfigConversionResults.test.ts @@ -105,9 +105,9 @@ function setupConversionEnvironment( conversionResults: createEmptySettingConversionResults({ converted: new Map([ [ - "tslint-setting-one", + "tslint-editor-setting-one", { - editorSettingName: "tslint-setting-one", + editorSettingName: "tslint-editor-setting-one", value: 42, }, ], diff --git a/src/editorSettings/convertEditorSetting.test.ts b/src/editorSettings/convertEditorSetting.test.ts index 6743c8044..e5b60c939 100644 --- a/src/editorSettings/convertEditorSetting.test.ts +++ b/src/editorSettings/convertEditorSetting.test.ts @@ -11,7 +11,7 @@ describe("convertEditorSetting", () => { // Act const result = convertEditorSetting( { - editorSettingName: "tslint-setting", + editorSettingName: "tslint-editor-setting", value: "any value", }, converters, @@ -32,13 +32,13 @@ describe("convertEditorSetting", () => { ], }; const converters = new Map([ - ["tslint-setting", () => converted], + ["tslint-editor-setting", () => converted], ]); // Act const result = convertEditorSetting( { - editorSettingName: "tslint-setting", + editorSettingName: "tslint-editor-setting", value: "existing value", }, converters, @@ -53,14 +53,14 @@ describe("convertEditorSetting", () => { const error = new Error("oh no"); const converters = new Map([ [ - "tslint-setting", + "tslint-editor-setting", () => { throw error; }, ], ]); const tsLintSetting: EditorSetting = { - editorSettingName: "tslint-setting", + editorSettingName: "tslint-editor-setting", value: "existing value", }; diff --git a/src/editorSettings/convertEditorSettings.test.ts b/src/editorSettings/convertEditorSettings.test.ts index 22fde39b1..b1d5bd890 100644 --- a/src/editorSettings/convertEditorSettings.test.ts +++ b/src/editorSettings/convertEditorSettings.test.ts @@ -127,7 +127,7 @@ function setupConversionEnvironment(conversionResult?: EditorSettingConversionRe function createSampleEditorSetting(): EditorSetting { return { - editorSettingName: "editor.tslint-setting-a", + editorSettingName: "editor.tslint-editor-setting-a", value: "a", }; } From 419b939a54a590dd1089ed05245ccd763f1e6131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20W=C3=BCrfel?= Date: Mon, 16 Dec 2019 18:47:56 +0100 Subject: [PATCH 41/41] fix: revert removal of no-explicit-any --- src/rules/converters/no-explicit-any.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/rules/converters/no-explicit-any.ts diff --git a/src/rules/converters/no-explicit-any.ts b/src/rules/converters/no-explicit-any.ts new file mode 100644 index 000000000..0a4af7e10 --- /dev/null +++ b/src/rules/converters/no-explicit-any.ts @@ -0,0 +1,11 @@ +import { RuleConverter } from "../converter"; + +export const convertNoExplicitAny: RuleConverter = () => { + return { + rules: [ + { + ruleName: "@typescript-eslint/no-explicit-any", + }, + ], + }; +};