Skip to content

Commit 204edfe

Browse files
MrCube42Josh Goldberg
authored and
Josh Goldberg
committed
Feature/convert editor settings 133 (#250)
* feat (editor): add cli option to specify editor config path to convert (defaults to vscode) * fix (editor): remove option configuration to fix default value * feat (editor): add editor cli option to TSLintToESLintSettings * feat(editor): conversion of multiple configs, read config and replace * test(editor): adjust tests to receive convertConfigs array * style (editor): fix incorrect import statement with js ending * fix(editor): get error return value instead of try/catch * style: format with prettier * fix: capture every error while processing multiple configs * fix: log success only once * feat(editor): add error for editor settings conversion * feat(editor): make editor conversion extendable like rule conversion, no reporting * refactor(editor): extract vscode settings path and editor config into new type files * fix: remove file ending from import statement * fix: change import of DeepPartial * feat(editor): report converted settings * refactor: extract general log outputs from report rules and settings convertions * test: report setting conversion results * test: conversion of editor.codeActions source.fixAll.tslint into eslint.autoFixOnSave * test: convert setting * test: convert settings, adjust missing and converted conversion results * test: exlcude settings converters from coverage * test: find editor configuration, stub file system * feat: simplify convertSettings because multiple setting changes don't apply yet * refactor: adjust naming of test variable * test: write editor config conversion results to proper path * test: write editor config output with sorted keys to file system * test: conversion of editor config * refactor: change generics into actual types * refactor: rename converters to specific rulesConverters and settingsConverters * test: clean up outcommented code * fix: change ignored coverage path * fix: add typing and dependency property name * fix: only convert editor settings from the editor configuration * fix: set the already converted setting properly to the conversion result (not the original setting) * feat: use findRawConfiguration to read editor configuration with json comments * test: adjust tests for usage of findRawConfiguration in findEditorConfiguration * refactor: specify naming, every "setting" to be an "editorSetting" * style: format imports * style: change sample name of editor-setting in tests * fix: revert removal of no-explicit-any
1 parent 8f355e8 commit 204edfe

31 files changed

+1338
-115
lines changed

jest.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module.exports = {
44
"!./src/**/*.d.ts",
55
"!./src/**/*.stubs.ts",
66
"!./src/adapters/*.ts",
7-
"!./src/rules/converters.ts",
7+
"!./src/rules/rulesConverters.ts",
8+
"!./src/editorSettings/editorSettingsConverters.ts",
89
"!./src/rules/mergers.ts",
910
"!./src/cli/main.ts",
1011
],

src/adapters/fileSystem.stub.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const createStubFileSystem = ({ data = {}, exists = true } = {}) => ({
2+
fileExists: jest.fn().mockReturnValue(exists),
3+
readFile: jest.fn().mockReturnValue(Promise.resolve(data)),
4+
writeFile: jest.fn(),
5+
});
6+
7+
export const createStubThrowingFileSystem = ({ err = "" } = {}) => ({
8+
fileExists: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))),
9+
readFile: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))),
10+
writeFile: jest.fn().mockRejectedValue(Promise.resolve(new Error(err))),
11+
});

src/cli/main.ts

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import { fsFileSystem } from "../adapters/fsFileSystem";
55
import { nativeImporter } from "../adapters/nativeImporter";
66
import { processLogger } from "../adapters/processLogger";
77
import { bind } from "../binding";
8-
import { ConvertConfigDependencies, convertConfig } from "../conversion/convertConfig";
8+
import { convertConfig, ConvertConfigDependencies } from "../conversion/convertConfig";
9+
import {
10+
convertEditorConfig,
11+
ConvertEditorConfigDependencies,
12+
} from "../conversion/convertEditorConfig";
913
import { removeExtendsDuplicatedRules } from "../creation/simplification/removeExtendsDuplicatedRules";
1014
import {
11-
RetrieveExtendsValuesDependencies,
1215
retrieveExtendsValues,
16+
RetrieveExtendsValuesDependencies,
1317
} from "../creation/simplification/retrieveExtendsValues";
1418
import {
1519
simplifyPackageRules,
@@ -19,30 +23,43 @@ import {
1923
writeConversionResults,
2024
WriteConversionResultsDependencies,
2125
} from "../creation/writeConversionResults";
26+
import { writeConversionResults as writeEditorConfigConversionResults } from "../creation/writeEditorConfigConversionResults";
27+
import {
28+
convertEditorSettings,
29+
ConvertEditorSettingsDependencies,
30+
} from "../editorSettings/convertEditorSettings";
31+
import { editorSettingsConverters } from "../editorSettings/editorSettingsConverters";
32+
import {
33+
findEditorConfiguration,
34+
FindEditorConfigurationDependencies,
35+
} from "../input/findEditorConfiguration";
36+
import { findESLintConfiguration } from "../input/findESLintConfiguration";
2237
import {
2338
findOriginalConfigurations,
2439
FindOriginalConfigurationsDependencies,
2540
} from "../input/findOriginalConfigurations";
2641
import { findPackagesConfiguration } from "../input/findPackagesConfiguration";
27-
import { findESLintConfiguration } from "../input/findESLintConfiguration";
2842
import { findTSLintConfiguration } from "../input/findTSLintConfiguration";
2943
import { findTypeScriptConfiguration } from "../input/findTypeScriptConfiguration";
3044
import { importer, ImporterDependencies } from "../input/importer";
3145
import { mergeLintConfigurations } from "../input/mergeLintConfigurations";
32-
import {
33-
reportConversionResults,
34-
ReportConversionResultsDependencies,
35-
} from "../reporting/reportConversionResults";
36-
import { converters } from "../rules/converters";
37-
import { convertRules } from "../rules/convertRules";
46+
import { ReportConversionResultsDependencies } from "../reporting/dependencies";
47+
import { reportConversionResults } from "../reporting/reportConversionResults";
48+
import { reportEditorSettingConversionResults } from "../reporting/reportEditorSettingConversionResults";
49+
import { convertRules, ConvertRulesDependencies } from "../rules/convertRules";
3850
import { mergers } from "../rules/mergers";
51+
import { rulesConverters } from "../rules/rulesConverters";
3952
import { runCli, RunCliDependencies } from "./runCli";
4053

41-
const convertRulesDependencies = {
42-
converters,
54+
const convertRulesDependencies: ConvertRulesDependencies = {
55+
converters: rulesConverters,
4356
mergers,
4457
};
4558

59+
const convertEditorSettingsDependencies: ConvertEditorSettingsDependencies = {
60+
converters: editorSettingsConverters,
61+
};
62+
4663
const nativeImporterDependencies: ImporterDependencies = {
4764
fileSystem: fsFileSystem,
4865
getCwd: () => process.cwd(),
@@ -56,6 +73,10 @@ const findConfigurationDependencies = {
5673
importer: boundImporter,
5774
};
5875

76+
const findEditorConfigurationDependencies: FindEditorConfigurationDependencies = {
77+
importer: boundImporter,
78+
};
79+
5980
const findOriginalConfigurationsDependencies: FindOriginalConfigurationsDependencies = {
6081
findESLintConfiguration: bind(findESLintConfiguration, findConfigurationDependencies),
6182
findPackagesConfiguration: bind(findPackagesConfiguration, findConfigurationDependencies),
@@ -81,6 +102,19 @@ const writeConversionResultsDependencies: WriteConversionResultsDependencies = {
81102
fileSystem: fsFileSystem,
82103
};
83104

105+
const convertEditorConfigDependencies: ConvertEditorConfigDependencies = {
106+
findEditorConfiguration: bind(findEditorConfiguration, findEditorConfigurationDependencies),
107+
convertEditorSettings: bind(convertEditorSettings, convertEditorSettingsDependencies),
108+
reportConversionResults: bind(
109+
reportEditorSettingConversionResults,
110+
reportConversionResultsDependencies,
111+
),
112+
writeConversionResults: bind(
113+
writeEditorConfigConversionResults,
114+
writeConversionResultsDependencies,
115+
),
116+
};
117+
84118
const convertConfigDependencies: ConvertConfigDependencies = {
85119
convertRules: bind(convertRules, convertRulesDependencies),
86120
findOriginalConfigurations: bind(
@@ -93,7 +127,10 @@ const convertConfigDependencies: ConvertConfigDependencies = {
93127
};
94128

95129
const runCliDependencies: RunCliDependencies = {
96-
convertConfig: bind(convertConfig, convertConfigDependencies),
130+
convertConfigs: [
131+
bind(convertConfig, convertConfigDependencies),
132+
bind(convertEditorConfig, convertEditorConfigDependencies),
133+
],
97134
logger: processLogger,
98135
};
99136

src/cli/runCli.test.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import { runCli, RunCliDependencies } from "./runCli";
88
const createStubArgv = (argv: string[] = []) => ["node", "some/path/bin/file", ...argv];
99

1010
const createStubRunCliDependencies = (
11-
overrides: Partial<Pick<RunCliDependencies, "convertConfig">> = {},
11+
overrides: Partial<Pick<RunCliDependencies, "convertConfigs">> = {},
1212
) => ({
13-
convertConfig: async (): Promise<TSLintToESLintResult> => ({ status: ResultStatus.Succeeded }),
13+
convertConfigs: [
14+
async (): Promise<TSLintToESLintResult> => ({ status: ResultStatus.Succeeded }),
15+
],
1416
logger: createStubLogger(),
1517
...overrides,
1618
});
@@ -32,7 +34,7 @@ describe("runCli", () => {
3234
// Arrange
3335
const message = "Oh no";
3436
const dependencies = createStubRunCliDependencies({
35-
convertConfig: () => Promise.reject(new Error(message)),
37+
convertConfigs: [() => Promise.reject(new Error(message))],
3638
});
3739

3840
// Act
@@ -49,11 +51,13 @@ describe("runCli", () => {
4951
// Arrange
5052
const complaint = "too much unit testing coverage";
5153
const dependencies = createStubRunCliDependencies({
52-
convertConfig: () =>
53-
Promise.resolve({
54-
complaints: [complaint],
55-
status: ResultStatus.ConfigurationError,
56-
}),
54+
convertConfigs: [
55+
() =>
56+
Promise.resolve({
57+
complaints: [complaint],
58+
status: ResultStatus.ConfigurationError,
59+
}),
60+
],
5761
});
5862

5963
// Act
@@ -72,11 +76,13 @@ describe("runCli", () => {
7276
// Arrange
7377
const error = new Error("too much unit testing coverage");
7478
const dependencies = createStubRunCliDependencies({
75-
convertConfig: () =>
76-
Promise.resolve({
77-
errors: [error],
78-
status: ResultStatus.Failed,
79-
}),
79+
convertConfigs: [
80+
() =>
81+
Promise.resolve({
82+
errors: [error],
83+
status: ResultStatus.Failed,
84+
}),
85+
],
8086
});
8187

8288
// Act
@@ -98,11 +104,13 @@ describe("runCli", () => {
98104
new Error("too much branch coverage"),
99105
];
100106
const dependencies = createStubRunCliDependencies({
101-
convertConfig: () =>
102-
Promise.resolve({
103-
errors,
104-
status: ResultStatus.Failed,
105-
}),
107+
convertConfigs: [
108+
() =>
109+
Promise.resolve({
110+
errors,
111+
status: ResultStatus.Failed,
112+
}),
113+
],
106114
});
107115

108116
// Act
@@ -133,12 +141,14 @@ describe("runCli", () => {
133141
it("default output should be .eslintrc.js", async () => {
134142
let defaultConfig;
135143
const dependencies = createStubRunCliDependencies({
136-
convertConfig: parsedArgs => {
137-
defaultConfig = parsedArgs.config;
138-
return Promise.resolve({
139-
status: ResultStatus.Succeeded,
140-
});
141-
},
144+
convertConfigs: [
145+
parsedArgs => {
146+
defaultConfig = parsedArgs.config;
147+
return Promise.resolve({
148+
status: ResultStatus.Succeeded,
149+
});
150+
},
151+
],
142152
});
143153

144154
const status = await runCli(dependencies, createStubArgv());

src/cli/runCli.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import chalk from "chalk";
2-
import { EOL } from "os";
32
import { Command } from "commander";
3+
import { EOL } from "os";
44

55
import { version } from "../../package.json";
66
import { Logger } from "../adapters/logger";
77
import { SansDependencies } from "../binding";
88
import { convertConfig } from "../conversion/convertConfig";
9-
import { TSLintToESLintSettings, TSLintToESLintResult, ResultStatus } from "../types";
9+
import { DEFAULT_VSCODE_SETTINGS_PATH } from "../input/vsCodeSettings";
10+
import { ResultStatus, ResultWithStatus, TSLintToESLintSettings } from "../types";
1011

1112
export type RunCliDependencies = {
12-
convertConfig: SansDependencies<typeof convertConfig>;
13+
convertConfigs: SansDependencies<typeof convertConfig>[];
1314
logger: Logger;
1415
};
1516

@@ -24,6 +25,11 @@ export const runCli = async (
2425
.option("--package [package]", "package configuration file to convert using")
2526
.option("--tslint [tslint]", "tslint configuration file to convert using")
2627
.option("--typescript [typescript]", "typescript configuration file to convert using")
28+
.option(
29+
"--editor [editor]",
30+
"editor configuration file to convert using",
31+
DEFAULT_VSCODE_SETTINGS_PATH,
32+
)
2733
.option("-V --version", "output the package version");
2834

2935
const parsedArgv = {
@@ -36,22 +42,38 @@ export const runCli = async (
3642
return ResultStatus.Succeeded;
3743
}
3844

39-
let result: TSLintToESLintResult;
45+
for (const convertConfig of dependencies.convertConfigs) {
46+
const result = await tryConvertConfig(convertConfig, parsedArgv);
47+
if (result.status !== ResultStatus.Succeeded) {
48+
logErrorResult(result, dependencies);
49+
return result.status;
50+
}
51+
}
52+
53+
dependencies.logger.stdout.write(chalk.greenBright("✅ All is well! ✅\n"));
54+
return ResultStatus.Succeeded;
55+
};
56+
57+
const tryConvertConfig = async (
58+
config: SansDependencies<typeof convertConfig>,
59+
argv: Partial<TSLintToESLintSettings>,
60+
): Promise<ResultWithStatus> => {
61+
let result: ResultWithStatus;
4062

4163
try {
42-
result = await dependencies.convertConfig(parsedArgv);
64+
result = await config(argv as TSLintToESLintSettings);
4365
} catch (error) {
4466
result = {
4567
errors: [error as Error],
4668
status: ResultStatus.Failed,
4769
};
4870
}
4971

50-
switch (result.status) {
51-
case ResultStatus.Succeeded:
52-
dependencies.logger.stdout.write(chalk.greenBright("✅ All is well! ✅\n"));
53-
break;
72+
return result;
73+
};
5474

75+
const logErrorResult = (result: ResultWithStatus, dependencies: RunCliDependencies) => {
76+
switch (result.status) {
5577
case ResultStatus.ConfigurationError:
5678
dependencies.logger.stderr.write(chalk.redBright("❌ "));
5779
dependencies.logger.stderr.write(chalk.red("Could not start tslint-to-eslint:"));
@@ -72,6 +94,4 @@ export const runCli = async (
7294
}
7395
break;
7496
}
75-
76-
return result.status;
7797
};

src/conversion/conversionResults.stubs.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings";
12
import { RuleConversionResults } from "../rules/convertRules";
23

34
export const createEmptyConversionResults = (
@@ -9,3 +10,12 @@ export const createEmptyConversionResults = (
910
plugins: new Set(),
1011
...overrides,
1112
});
13+
14+
export const createEmptySettingConversionResults = (
15+
overrides: Partial<EditorSettingConversionResults> = {},
16+
): EditorSettingConversionResults => ({
17+
converted: new Map(),
18+
failed: [],
19+
missing: [],
20+
...overrides,
21+
});

0 commit comments

Comments
 (0)