From 9c6cbff2a0458018ad7fd0c251c941bdb6f6f47c Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 4 May 2020 00:03:24 -0400 Subject: [PATCH 1/7] WIP: logic for deduplicating ESLint rules' extensions --- docs/Architecture.md | 4 +-- src/cli/main.ts | 16 +++++----- src/conversion/conversionResults.stubs.ts | 8 +++-- src/conversion/convertConfig.test.ts | 3 +- src/conversion/convertConfig.ts | 16 +++++----- .../collectTSLintRulesets.test.ts | 0 .../collectTSLintRulesets.ts | 0 .../prettier/addPrettierExtensions.test.ts | 0 .../prettier/addPrettierExtensions.ts | 0 .../removeExtendsDuplicatedRules.test.ts | 16 +++++----- .../removeExtendsDuplicatedRules.ts | 8 ++--- .../resolveExtensionNames.test.ts | 0 .../resolveExtensionNames.ts | 0 .../retrieveExtendsValues.test.ts | 0 .../retrieveExtendsValues.ts | 0 .../summarizePackageRules.test.ts} | 29 ++++++++++--------- .../summarizePackageRules.ts} | 24 ++++++++------- src/creation/summarization/types.ts | 7 +++++ src/creation/writeConversionResults.test.ts | 4 +-- src/creation/writeConversionResults.ts | 12 ++++---- .../packages/logMissingPackages.test.ts | 18 ------------ src/reporting/packages/logMissingPackages.ts | 6 ++-- src/reporting/reportConversionResults.test.ts | 21 +------------- src/reporting/reportConversionResults.ts | 6 ++-- 24 files changed, 87 insertions(+), 111 deletions(-) rename src/creation/{simplification => summarization}/collectTSLintRulesets.test.ts (100%) rename src/creation/{simplification => summarization}/collectTSLintRulesets.ts (100%) rename src/creation/{simplification => summarization}/prettier/addPrettierExtensions.test.ts (100%) rename src/creation/{simplification => summarization}/prettier/addPrettierExtensions.ts (100%) rename src/creation/{simplification => summarization}/removeExtendsDuplicatedRules.test.ts (84%) rename src/creation/{simplification => summarization}/removeExtendsDuplicatedRules.ts (91%) rename src/creation/{simplification => summarization}/resolveExtensionNames.test.ts (100%) rename src/creation/{simplification => summarization}/resolveExtensionNames.ts (100%) rename src/creation/{simplification => summarization}/retrieveExtendsValues.test.ts (100%) rename src/creation/{simplification => summarization}/retrieveExtendsValues.ts (100%) rename src/creation/{simplification/simplifyPackageRules.test.ts => summarization/summarizePackageRules.test.ts} (79%) rename src/creation/{simplification/simplifyPackageRules.ts => summarization/summarizePackageRules.ts} (80%) create mode 100644 src/creation/summarization/types.ts diff --git a/docs/Architecture.md b/docs/Architecture.md index 4ec5bc349..660a3f22a 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -13,9 +13,9 @@ Within `src/conversion/convertConfig.ts`, the following steps occur: 1. Existing configurations are read from disk 2. TSLint rules are converted into their ESLint configurations -3. ESLint configurations are simplified based on extended ESLint and TSLint presets +3. ESLint configurations are summarized based on extended ESLint and TSLint presets - 3a. If no output rules conflict with `eslint-config-prettier`, it's added in -4. The simplified configuration is written to the output config file +4. The summarized configuration is written to the output config file 5. Files to transform comments in have source text rewritten using the same rule conversion logic 6. A summary of the results is printed to the user's console diff --git a/src/cli/main.ts b/src/cli/main.ts index 0b0f4bbb2..093dc5238 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -16,16 +16,16 @@ import { convertEditorConfig, ConvertEditorConfigDependencies, } from "../conversion/convertEditorConfig"; -import { addPrettierExtensions } from "../creation/simplification/prettier/addPrettierExtensions"; -import { removeExtendsDuplicatedRules } from "../creation/simplification/removeExtendsDuplicatedRules"; +import { addPrettierExtensions } from "../creation/summarization/prettier/addPrettierExtensions"; +import { removeExtendsDuplicatedRules } from "../creation/summarization/removeExtendsDuplicatedRules"; import { retrieveExtendsValues, RetrieveExtendsValuesDependencies, -} from "../creation/simplification/retrieveExtendsValues"; +} from "../creation/summarization/retrieveExtendsValues"; import { - simplifyPackageRules, - SimplifyPackageRulesDependencies, -} from "../creation/simplification/simplifyPackageRules"; + summarizePackageRules, + SummarizePackageRulesDependencies, +} from "../creation/summarization/summarizePackageRules"; import { writeConversionResults, WriteConversionResultsDependencies, @@ -138,7 +138,7 @@ const retrieveExtendsValuesDependencies: RetrieveExtendsValuesDependencies = { importer: boundImporter, }; -const simplifyPackageRulesDependencies: SimplifyPackageRulesDependencies = { +const summarizePackageRulesDependencies: SummarizePackageRulesDependencies = { addPrettierExtensions, removeExtendsDuplicatedRules, retrieveExtendsValues: bind(retrieveExtendsValues, retrieveExtendsValuesDependencies), @@ -175,7 +175,7 @@ const convertConfigDependencies: ConvertConfigDependencies = { logMissingPackages: bind(logMissingPackages, logMissingPackagesDependencies), reportCommentResults: bind(reportCommentResults, reportCommentResultsDependencies), reportConversionResults: bind(reportConversionResults, reportConversionResultsDependencies), - simplifyPackageRules: bind(simplifyPackageRules, simplifyPackageRulesDependencies), + summarizePackageRules: bind(summarizePackageRules, summarizePackageRulesDependencies), writeConversionResults: bind(writeConversionResults, writeConversionResultsDependencies), }; diff --git a/src/conversion/conversionResults.stubs.ts b/src/conversion/conversionResults.stubs.ts index fbcc05dd8..b669023c4 100644 --- a/src/conversion/conversionResults.stubs.ts +++ b/src/conversion/conversionResults.stubs.ts @@ -1,10 +1,12 @@ +import { SummarizedResultsConfiguration } from "../creation/summarization/types"; import { EditorSettingConversionResults } from "../editorSettings/convertEditorSettings"; -import { SimplifiedResultsConfiguration } from "../creation/simplification/simplifyPackageRules"; export const createEmptyConversionResults = ( - overrides: Partial = {}, -): SimplifiedResultsConfiguration => ({ + overrides: Partial = {}, +): SummarizedResultsConfiguration => ({ converted: new Map(), + extends: [], + extensionRules: new Map(), failed: [], missing: [], plugins: new Set(), diff --git a/src/conversion/convertConfig.test.ts b/src/conversion/convertConfig.test.ts index d674366a5..7e7945230 100644 --- a/src/conversion/convertConfig.test.ts +++ b/src/conversion/convertConfig.test.ts @@ -16,10 +16,11 @@ const createStubDependencies = ( }), reportCommentResults: jest.fn(), reportConversionResults: jest.fn(), - simplifyPackageRules: async (_configurations, data) => ({ + summarizePackageRules: async (_configurations, data) => ({ ...data, converted: new Map(), extends: [], + extensionRules: new Map(), failed: [], missing: [], plugins: new Set(), diff --git a/src/conversion/convertConfig.ts b/src/conversion/convertConfig.ts index 5b1bb2b74..472f55c5a 100644 --- a/src/conversion/convertConfig.ts +++ b/src/conversion/convertConfig.ts @@ -1,6 +1,6 @@ import { SansDependencies } from "../binding"; import { convertComments } from "../comments/convertComments"; -import { simplifyPackageRules } from "../creation/simplification/simplifyPackageRules"; +import { summarizePackageRules } from "../creation/summarization/summarizePackageRules"; import { writeConversionResults } from "../creation/writeConversionResults"; import { findOriginalConfigurations } from "../input/findOriginalConfigurations"; import { logMissingPackages } from "../reporting/packages/logMissingPackages"; @@ -16,7 +16,7 @@ export type ConvertConfigDependencies = { logMissingPackages: SansDependencies; reportCommentResults: SansDependencies; reportConversionResults: SansDependencies; - simplifyPackageRules: SansDependencies; + summarizePackageRules: SansDependencies; writeConversionResults: SansDependencies; }; @@ -39,18 +39,18 @@ export const convertConfig = async ( originalConfigurations.data.tslint.full.rules, ); - // 3. ESLint configurations are simplified based on extended ESLint and TSLint presets - const simplifiedConfiguration = await dependencies.simplifyPackageRules( + // 3. ESLint configurations are summarized based on extended ESLint and TSLint presets + const summarizedConfiguration = await dependencies.summarizePackageRules( originalConfigurations.data.eslint, originalConfigurations.data.tslint, ruleConversionResults, settings.prettier, ); - // 4. The simplified configuration is written to the output config file + // 4. The summarized configuration is written to the output config file const fileWriteError = await dependencies.writeConversionResults( settings.config, - simplifiedConfiguration, + summarizedConfiguration, originalConfigurations.data, ); if (fileWriteError !== undefined) { @@ -64,10 +64,10 @@ export const convertConfig = async ( const commentsResult = await dependencies.convertComments(settings.comments); // 6. A summary of the results is printed to the user's console - await dependencies.reportConversionResults(settings.config, simplifiedConfiguration); + await dependencies.reportConversionResults(settings.config, summarizedConfiguration); dependencies.reportCommentResults(commentsResult); await dependencies.logMissingPackages( - simplifiedConfiguration, + summarizedConfiguration, originalConfigurations.data.packages, ); diff --git a/src/creation/simplification/collectTSLintRulesets.test.ts b/src/creation/summarization/collectTSLintRulesets.test.ts similarity index 100% rename from src/creation/simplification/collectTSLintRulesets.test.ts rename to src/creation/summarization/collectTSLintRulesets.test.ts diff --git a/src/creation/simplification/collectTSLintRulesets.ts b/src/creation/summarization/collectTSLintRulesets.ts similarity index 100% rename from src/creation/simplification/collectTSLintRulesets.ts rename to src/creation/summarization/collectTSLintRulesets.ts diff --git a/src/creation/simplification/prettier/addPrettierExtensions.test.ts b/src/creation/summarization/prettier/addPrettierExtensions.test.ts similarity index 100% rename from src/creation/simplification/prettier/addPrettierExtensions.test.ts rename to src/creation/summarization/prettier/addPrettierExtensions.test.ts diff --git a/src/creation/simplification/prettier/addPrettierExtensions.ts b/src/creation/summarization/prettier/addPrettierExtensions.ts similarity index 100% rename from src/creation/simplification/prettier/addPrettierExtensions.ts rename to src/creation/summarization/prettier/addPrettierExtensions.ts diff --git a/src/creation/simplification/removeExtendsDuplicatedRules.test.ts b/src/creation/summarization/removeExtendsDuplicatedRules.test.ts similarity index 84% rename from src/creation/simplification/removeExtendsDuplicatedRules.test.ts rename to src/creation/summarization/removeExtendsDuplicatedRules.test.ts index 5c64be1d4..f104966c0 100644 --- a/src/creation/simplification/removeExtendsDuplicatedRules.test.ts +++ b/src/creation/summarization/removeExtendsDuplicatedRules.test.ts @@ -43,7 +43,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, [{}]); + const { differentRules } = removeExtendsDuplicatedRules(allRules, [{}]); // Assert expect(differentRules.size).toBe(1); @@ -59,7 +59,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -75,7 +75,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -91,7 +91,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -107,7 +107,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -123,7 +123,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -140,7 +140,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -157,7 +157,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const differentRules = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); diff --git a/src/creation/simplification/removeExtendsDuplicatedRules.ts b/src/creation/summarization/removeExtendsDuplicatedRules.ts similarity index 91% rename from src/creation/simplification/removeExtendsDuplicatedRules.ts rename to src/creation/summarization/removeExtendsDuplicatedRules.ts index 2e1744699..19361b4f9 100644 --- a/src/creation/simplification/removeExtendsDuplicatedRules.ts +++ b/src/creation/summarization/removeExtendsDuplicatedRules.ts @@ -10,17 +10,17 @@ import { ESLintRuleOptions } from "../../rules/types"; export const removeExtendsDuplicatedRules = ( allRules: Map, extensions: Partial[], -): Map => { +) => { const differentRules = new Map(); - const mergedExtensionRules = mergeExtensions(extensions); + const extensionRules = mergeExtensions(extensions); for (const [ruleName, value] of allRules) { - if (!ruleValuesAreTheSame(value, mergedExtensionRules.get(ruleName))) { + if (ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { differentRules.set(ruleName, value); } } - return differentRules; + return { differentRules, extensionRules }; }; const mergeExtensions = (extensions: Partial[]) => { diff --git a/src/creation/simplification/resolveExtensionNames.test.ts b/src/creation/summarization/resolveExtensionNames.test.ts similarity index 100% rename from src/creation/simplification/resolveExtensionNames.test.ts rename to src/creation/summarization/resolveExtensionNames.test.ts diff --git a/src/creation/simplification/resolveExtensionNames.ts b/src/creation/summarization/resolveExtensionNames.ts similarity index 100% rename from src/creation/simplification/resolveExtensionNames.ts rename to src/creation/summarization/resolveExtensionNames.ts diff --git a/src/creation/simplification/retrieveExtendsValues.test.ts b/src/creation/summarization/retrieveExtendsValues.test.ts similarity index 100% rename from src/creation/simplification/retrieveExtendsValues.test.ts rename to src/creation/summarization/retrieveExtendsValues.test.ts diff --git a/src/creation/simplification/retrieveExtendsValues.ts b/src/creation/summarization/retrieveExtendsValues.ts similarity index 100% rename from src/creation/simplification/retrieveExtendsValues.ts rename to src/creation/summarization/retrieveExtendsValues.ts diff --git a/src/creation/simplification/simplifyPackageRules.test.ts b/src/creation/summarization/summarizePackageRules.test.ts similarity index 79% rename from src/creation/simplification/simplifyPackageRules.test.ts rename to src/creation/summarization/summarizePackageRules.test.ts index 5bde76411..bb8d4a835 100644 --- a/src/creation/simplification/simplifyPackageRules.test.ts +++ b/src/creation/summarization/summarizePackageRules.test.ts @@ -1,9 +1,9 @@ import { ConfigurationError } from "../../errors/configurationError"; import { ESLintRuleOptions } from "../../rules/types"; import { createEmptyConversionResults } from "../../conversion/conversionResults.stubs"; -import { simplifyPackageRules, SimplifyPackageRulesDependencies } from "./simplifyPackageRules"; +import { summarizePackageRules, SummarizePackageRulesDependencies } from "./summarizePackageRules"; -const createStubDependencies = (overrides: Partial = {}) => ({ +const createStubDependencies = (overrides: Partial = {}) => ({ addPrettierExtensions: jest.fn(), removeExtendsDuplicatedRules: jest.fn(), retrieveExtendsValues: async () => ({ @@ -26,7 +26,7 @@ const createStubTSLintConfiguration = () => ({ raw: {}, }); -describe("simplifyPackageRules", () => { +describe("summarizePackageRules", () => { it("returns equivalent conversion results when there is no loaded ESLint configuration and no TSLint extensions", async () => { // Arrange const dependencies = createStubDependencies(); @@ -35,7 +35,7 @@ describe("simplifyPackageRules", () => { const ruleConversionResults = createEmptyConversionResults(); // Act - const simplifiedResults = await simplifyPackageRules( + const summarizedResults = await summarizePackageRules( dependencies, eslint, tslint, @@ -43,7 +43,7 @@ describe("simplifyPackageRules", () => { ); // Assert - expect(simplifiedResults).toEqual(ruleConversionResults); + expect(summarizedResults).toEqual(ruleConversionResults); }); it("adds Prettier extensions when addPrettierExtensions returns true", async () => { @@ -56,7 +56,7 @@ describe("simplifyPackageRules", () => { const ruleConversionResults = createEmptyConversionResults(); // Act - const simplifiedResults = await simplifyPackageRules( + const summarizedResults = await summarizePackageRules( dependencies, eslint, tslint, @@ -65,7 +65,7 @@ describe("simplifyPackageRules", () => { ); // Assert - expect(simplifiedResults).toEqual({ + expect(summarizedResults).toEqual({ ...ruleConversionResults, converted: undefined, extends: ["prettier", "prettier/@typescript-eslint"], @@ -80,7 +80,7 @@ describe("simplifyPackageRules", () => { const ruleConversionResults = createEmptyConversionResults(); // Act - const simplifiedResults = await simplifyPackageRules( + const summarizedResults = await summarizePackageRules( dependencies, eslint, tslint, @@ -88,13 +88,13 @@ describe("simplifyPackageRules", () => { ); // Assert - expect(simplifiedResults).toEqual(ruleConversionResults); + expect(summarizedResults).toEqual(ruleConversionResults); }); it("includes deduplicated rules and extension failures when the ESLint configuration extends", async () => { // Arrange const configurationErrors = [new ConfigurationError(new Error("oh no"), "darn")]; - const deduplicatedRules = new Map([ + const differentRules = new Map([ [ "rule-name", { @@ -104,8 +104,9 @@ describe("simplifyPackageRules", () => { }, ], ]); + const extensionRules = new Map(differentRules); const dependencies = createStubDependencies({ - removeExtendsDuplicatedRules: () => deduplicatedRules, + removeExtendsDuplicatedRules: () => ({ differentRules, extensionRules }), retrieveExtendsValues: async () => ({ configurationErrors, importedExtensions: [], @@ -117,7 +118,7 @@ describe("simplifyPackageRules", () => { const ruleConversionResults = createEmptyConversionResults(); // Act - const simplifiedResults = await simplifyPackageRules( + const summarizedResults = await summarizePackageRules( dependencies, eslint, tslint, @@ -125,9 +126,9 @@ describe("simplifyPackageRules", () => { ); // Assert - expect(simplifiedResults).toEqual({ + expect(summarizedResults).toEqual({ ...ruleConversionResults, - converted: deduplicatedRules, + converted: differentRules, extends: [...eslintExtends], failed: configurationErrors, }); diff --git a/src/creation/simplification/simplifyPackageRules.ts b/src/creation/summarization/summarizePackageRules.ts similarity index 80% rename from src/creation/simplification/simplifyPackageRules.ts rename to src/creation/summarization/summarizePackageRules.ts index b7df6f39e..48d737bdf 100644 --- a/src/creation/simplification/simplifyPackageRules.ts +++ b/src/creation/summarization/summarizePackageRules.ts @@ -8,28 +8,25 @@ import { collectTSLintRulesets } from "./collectTSLintRulesets"; import { addPrettierExtensions } from "./prettier/addPrettierExtensions"; import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; import { retrieveExtendsValues } from "./retrieveExtendsValues"; +import { SummarizedResultsConfiguration } from "./types"; -export type SimplifyPackageRulesDependencies = { +export type SummarizePackageRulesDependencies = { addPrettierExtensions: typeof addPrettierExtensions; removeExtendsDuplicatedRules: typeof removeExtendsDuplicatedRules; retrieveExtendsValues: SansDependencies; }; -export type SimplifiedResultsConfiguration = RuleConversionResults & { - extends?: string[]; -}; - /** * Given an initial set of rule conversion results and original configurations, * determines which ESLint rulesets to extend from and removes redundant rule values. */ -export const simplifyPackageRules = async ( - dependencies: SimplifyPackageRulesDependencies, +export const summarizePackageRules = async ( + dependencies: SummarizePackageRulesDependencies, eslint: Pick, "full"> | undefined, tslint: OriginalConfigurations>, ruleConversionResults: RuleConversionResults, prettierRequested?: boolean, -): Promise => { +): Promise => { const extendedESLintRulesets = eslint?.full.extends ?? []; const extendedTSLintRulesets = collectTSLintRulesets(tslint); const allExtensions = uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets); @@ -40,22 +37,27 @@ export const simplifyPackageRules = async ( } if (allExtensions.length === 0) { - return ruleConversionResults; + return { + ...ruleConversionResults, + extends: [], + extensionRules: new Map(), + }; } const { configurationErrors, importedExtensions } = await dependencies.retrieveExtendsValues( uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets), ); - const converted = dependencies.removeExtendsDuplicatedRules( + const deduplication = dependencies.removeExtendsDuplicatedRules( ruleConversionResults.converted, importedExtensions, ); return { ...ruleConversionResults, - converted, + converted: deduplication.differentRules, extends: uniqueFromSources(allExtensions), + extensionRules: deduplication.extensionRules, failed: [...ruleConversionResults.failed, ...configurationErrors], }; }; diff --git a/src/creation/summarization/types.ts b/src/creation/summarization/types.ts new file mode 100644 index 000000000..250ae65af --- /dev/null +++ b/src/creation/summarization/types.ts @@ -0,0 +1,7 @@ +import { RuleConversionResults } from "../../rules/convertRules"; +import { ESLintRuleOptions } from "../../rules/types"; + +export type SummarizedResultsConfiguration = RuleConversionResults & { + extends: string[]; + extensionRules: Map; +}; diff --git a/src/creation/writeConversionResults.test.ts b/src/creation/writeConversionResults.test.ts index 95c66ff7f..d78c66e78 100644 --- a/src/creation/writeConversionResults.test.ts +++ b/src/creation/writeConversionResults.test.ts @@ -1,11 +1,11 @@ import { createEmptyConversionResults } from "../conversion/conversionResults.stubs"; import { AllOriginalConfigurations } from "../input/findOriginalConfigurations"; import { formatJsonOutput } from "./formatting/formatters/formatJsonOutput"; -import { SimplifiedResultsConfiguration } from "./simplification/simplifyPackageRules"; +import { SummarizedResultsConfiguration } from "./summarization/types"; import { writeConversionResults } from "./writeConversionResults"; const createStubOriginalConfigurations = ( - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ tslint: { full: { diff --git a/src/creation/writeConversionResults.ts b/src/creation/writeConversionResults.ts index cc379215b..acd1e76a5 100644 --- a/src/creation/writeConversionResults.ts +++ b/src/creation/writeConversionResults.ts @@ -3,7 +3,7 @@ import { AllOriginalConfigurations } from "../input/findOriginalConfigurations"; import { createEnv } from "./eslint/createEnv"; import { formatConvertedRules } from "./formatConvertedRules"; import { formatOutput } from "./formatting/formatOutput"; -import { SimplifiedResultsConfiguration } from "./simplification/simplifyPackageRules"; +import { SummarizedResultsConfiguration } from "./summarization/types"; export type WriteConversionResultsDependencies = { fileSystem: Pick; @@ -12,13 +12,13 @@ export type WriteConversionResultsDependencies = { export const writeConversionResults = async ( dependencies: WriteConversionResultsDependencies, outputPath: string, - ruleConversionResults: SimplifiedResultsConfiguration, + summarizedResults: SummarizedResultsConfiguration, originalConfigurations: AllOriginalConfigurations, ) => { const plugins = ["@typescript-eslint"]; const { eslint, tslint } = originalConfigurations; - if (ruleConversionResults.missing.length !== 0) { + if (summarizedResults.missing.length !== 0) { plugins.push("@typescript-eslint/tslint"); } @@ -26,7 +26,7 @@ export const writeConversionResults = async ( ...eslint?.full, env: createEnv(originalConfigurations), ...(eslint && { globals: eslint.raw.globals }), - ...(ruleConversionResults.extends && { extends: ruleConversionResults.extends }), + ...(summarizedResults.extends && { extends: summarizedResults.extends }), parser: "@typescript-eslint/parser", parserOptions: { project: "tsconfig.json", @@ -34,8 +34,8 @@ export const writeConversionResults = async ( }, plugins, rules: { - ...eslint?.full.rules, - ...formatConvertedRules(ruleConversionResults, tslint.full), + ...formatESLintRules(eslint?.full.rules, summarizedResults), + ...formatConvertedRules(summarizedResults, tslint.full), }, }; diff --git a/src/reporting/packages/logMissingPackages.test.ts b/src/reporting/packages/logMissingPackages.test.ts index 7396d2570..670c28cd8 100644 --- a/src/reporting/packages/logMissingPackages.test.ts +++ b/src/reporting/packages/logMissingPackages.test.ts @@ -50,24 +50,6 @@ describe("logMissingPackages", () => { ); }); - it("does not include eslint-config-prettier when there are no extensions", async () => { - // Arrange - const { choosePackageManager, logger } = createStubDependencies(); - const ruleConversionResults = createEmptyConversionResults({ - extends: undefined, - }); - - // Act - await logMissingPackages({ choosePackageManager, logger }, ruleConversionResults); - - // Assert - expectEqualWrites( - logger.stdout.write, - `⚡ 3 new packages are required for this ESLint configuration. ⚡`, - ` npm install @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint --save-dev`, - ); - }); - it("does not include eslint-config-prettier when extensions don't include eslint-config-prettier", async () => { // Arrange const { choosePackageManager, logger } = createStubDependencies(); diff --git a/src/reporting/packages/logMissingPackages.ts b/src/reporting/packages/logMissingPackages.ts index 8a662e6a1..38b93e0ae 100644 --- a/src/reporting/packages/logMissingPackages.ts +++ b/src/reporting/packages/logMissingPackages.ts @@ -3,7 +3,7 @@ import { EOL } from "os"; import { Logger } from "../../adapters/logger"; import { SansDependencies } from "../../binding"; -import { SimplifiedResultsConfiguration } from "../../creation/simplification/simplifyPackageRules"; +import { SummarizedResultsConfiguration } from "../../creation/summarization/types"; import { PackagesConfiguration } from "../../input/findPackagesConfiguration"; import { isTruthy } from "../../utils"; import { installationMessages } from "../packages/packageManagers"; @@ -16,7 +16,7 @@ export type LogMissingPackagesDependencies = { export const logMissingPackages = async ( dependencies: LogMissingPackagesDependencies, - ruleConversionResults: Pick, + ruleConversionResults: Pick, packageConfiguration?: PackagesConfiguration, ) => { const packageManager = await dependencies.choosePackageManager(); @@ -29,7 +29,7 @@ export const logMissingPackages = async ( const requiredPackageNames = [ "@typescript-eslint/eslint-plugin", "@typescript-eslint/parser", - ruleConversionResults.extends?.join("").includes("prettier") && "eslint-config-prettier", + ruleConversionResults.extends.join("").includes("prettier") && "eslint-config-prettier", ruleConversionResults.missing.length !== 0 && "@typescript-eslint/eslint-plugin-tslint", "eslint", ...Array.from(ruleConversionResults.plugins), diff --git a/src/reporting/reportConversionResults.test.ts b/src/reporting/reportConversionResults.test.ts index 75c6da81f..92ccf77a9 100644 --- a/src/reporting/reportConversionResults.test.ts +++ b/src/reporting/reportConversionResults.test.ts @@ -225,26 +225,7 @@ describe("reportConversionResults", () => { ); }); - it("logs a Prettier recommendation when there are no extensions", async () => { - // Arrange - const logger = createStubLogger(); - const conversionResults = createEmptyConversionResults({ - extends: undefined, - }); - - // Act - await reportConversionResults({ logger }, ".eslintrc.js", conversionResults); - - // Assert - expectEqualWrites( - logger.stdout.write, - `☠ Prettier plugins are missing from your configuration. ☠`, - ` We highly recommend running tslint-to-eslint-config --prettier to disable formatting ESLint rules.`, - ` See https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md#should-i-use-prettier.`, - ); - }); - - it("logs a Prettier recommendation when extends don't include eslint-config-prettier", async () => { + it("logs a Prettier recommendation when extends doesn't include eslint-config-prettier", async () => { // Arrange const logger = createStubLogger(); const conversionResults = createEmptyConversionResults({ diff --git a/src/reporting/reportConversionResults.ts b/src/reporting/reportConversionResults.ts index d3949eb77..29926dc19 100644 --- a/src/reporting/reportConversionResults.ts +++ b/src/reporting/reportConversionResults.ts @@ -2,7 +2,7 @@ import chalk from "chalk"; import { EOL } from "os"; import { Logger } from "../adapters/logger"; -import { SimplifiedResultsConfiguration } from "../creation/simplification/simplifyPackageRules"; +import { SummarizedResultsConfiguration } from "../creation/summarization/types"; import { ESLintRuleOptions, TSLintRuleOptions } from "../rules/types"; import { logFailedConversions, @@ -17,7 +17,7 @@ export type ReportConversionResultsDependencies = { export const reportConversionResults = async ( dependencies: ReportConversionResultsDependencies, outputPath: string, - ruleConversionResults: SimplifiedResultsConfiguration, + ruleConversionResults: SummarizedResultsConfiguration, ) => { if (ruleConversionResults.converted.size !== 0) { logSuccessfulConversions("rule", ruleConversionResults.converted, dependencies.logger); @@ -42,7 +42,7 @@ export const reportConversionResults = async ( ); } - if (!ruleConversionResults.extends?.join("").includes("prettier")) { + if (!ruleConversionResults.extends.join("").includes("prettier")) { logPrettierExtension(dependencies.logger); } }; From 9aa1686b748a72e70183cbfb074ec437a22acf4c Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 13:44:03 -0400 Subject: [PATCH 2/7] Whoa, it actually works --- package-lock.json | 6 +++ package.json | 1 + src/cli/main.ts | 4 +- src/creation/eslint/trimESLintRules.ts | 26 +++++++++++++ .../removeAllExtendsDuplicatedRules.test.ts} | 20 +++++----- .../removeAllExtendsDuplicatedRules.ts} | 35 ++--------------- .../pruning/removeExtendsDuplicatedRules.ts | 38 +++++++++++++++++++ .../summarizePackageRules.test.ts | 4 +- .../summarization/summarizePackageRules.ts | 6 +-- src/creation/writeConversionResults.ts | 3 +- src/input/findESLintConfiguration.ts | 9 +---- src/rules/convertRuleSeverity.ts | 28 -------------- src/rules/convertRules.ts | 4 +- src/rules/formatRawTslintRule.test.ts | 2 +- .../{ => formats}/convertRuleSeverity.test.ts | 37 +----------------- src/rules/formats/convertRuleSeverity.ts | 19 ++++++++++ .../formats/convertTSLintRuleSeverity.test.ts | 36 ++++++++++++++++++ .../formats/convertTSLintRuleSeverity.ts | 10 +++++ src/rules/formats/formatRawESLintRule.ts | 12 ++++++ .../{ => formats}/formatRawTslintRule.ts | 2 +- src/rules/types.ts | 2 + src/typings/eslint-config-prettier.d.ts | 4 -- 22 files changed, 180 insertions(+), 128 deletions(-) create mode 100644 src/creation/eslint/trimESLintRules.ts rename src/creation/{summarization/removeExtendsDuplicatedRules.test.ts => pruning/removeAllExtendsDuplicatedRules.test.ts} (81%) rename src/creation/{summarization/removeExtendsDuplicatedRules.ts => pruning/removeAllExtendsDuplicatedRules.ts} (60%) create mode 100644 src/creation/pruning/removeExtendsDuplicatedRules.ts delete mode 100644 src/rules/convertRuleSeverity.ts rename src/rules/{ => formats}/convertRuleSeverity.test.ts (52%) create mode 100644 src/rules/formats/convertRuleSeverity.ts create mode 100644 src/rules/formats/convertTSLintRuleSeverity.test.ts create mode 100644 src/rules/formats/convertTSLintRuleSeverity.ts create mode 100644 src/rules/formats/formatRawESLintRule.ts rename src/rules/{ => formats}/formatRawTslintRule.ts (81%) delete mode 100644 src/typings/eslint-config-prettier.d.ts diff --git a/package-lock.json b/package-lock.json index 7dd553e55..5ef8ccfae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3063,6 +3063,12 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@types/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-UBuZMZVog9c9jXvArbYtWH570sRWNaU6kEnUAHsHb/+zAufzPT4I+gMkUR2dVPWlqiceoRU1thjUVdGrAWVpCA==", + "dev": true + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", diff --git a/package.json b/package.json index a5635a81a..8d7410fde 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@babel/plugin-proposal-optional-chaining": "7.9.0", "@babel/preset-env": "7.9.6", "@babel/preset-typescript": "7.9.0", + "@types/eslint-config-prettier": "^6.11.0", "@types/glob": "7.1.1", "@types/jest": "25.2.1", "@types/node": "12.12.21", diff --git a/src/cli/main.ts b/src/cli/main.ts index 093dc5238..2e4d536f0 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -16,8 +16,8 @@ import { convertEditorConfig, ConvertEditorConfigDependencies, } from "../conversion/convertEditorConfig"; +import { removeAllExtendsDuplicatedRules } from "../creation/pruning/removeAllExtendsDuplicatedRules"; import { addPrettierExtensions } from "../creation/summarization/prettier/addPrettierExtensions"; -import { removeExtendsDuplicatedRules } from "../creation/summarization/removeExtendsDuplicatedRules"; import { retrieveExtendsValues, RetrieveExtendsValuesDependencies, @@ -140,7 +140,7 @@ const retrieveExtendsValuesDependencies: RetrieveExtendsValuesDependencies = { const summarizePackageRulesDependencies: SummarizePackageRulesDependencies = { addPrettierExtensions, - removeExtendsDuplicatedRules, + removeAllExtendsDuplicatedRules, retrieveExtendsValues: bind(retrieveExtendsValues, retrieveExtendsValuesDependencies), }; diff --git a/src/creation/eslint/trimESLintRules.ts b/src/creation/eslint/trimESLintRules.ts new file mode 100644 index 000000000..f0ee58223 --- /dev/null +++ b/src/creation/eslint/trimESLintRules.ts @@ -0,0 +1,26 @@ +import { ESLintConfigurationRules } from "../../input/findESLintConfiguration"; +import { ESLintRuleOptions } from "../../rules/types"; +import { removeExtendsDuplicatedRules } from "../pruning/removeExtendsDuplicatedRules"; +import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; + +export const trimESLintRules = ( + rules: ESLintConfigurationRules | undefined, + extensionRules: Map, +) => { + if (rules === undefined) { + return undefined; + } + + const parsedRules = Object.entries(rules).map(([ruleName, configuration]): [ + string, + ESLintRuleOptions, + ] => { + const [rawRuleSeverity, ruleArguments] = + configuration instanceof Array ? configuration : [configuration, {}]; + const ruleSeverity = convertRawESLintRuleSeverity(rawRuleSeverity); + + return [ruleName, { ruleArguments, ruleName, ruleSeverity }]; + }); + + return removeExtendsDuplicatedRules(new Map(parsedRules), extensionRules); +}; diff --git a/src/creation/summarization/removeExtendsDuplicatedRules.test.ts b/src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts similarity index 81% rename from src/creation/summarization/removeExtendsDuplicatedRules.test.ts rename to src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts index f104966c0..3265f0217 100644 --- a/src/creation/summarization/removeExtendsDuplicatedRules.test.ts +++ b/src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts @@ -3,7 +3,7 @@ import { ESLintConfigurationRuleValue, } from "../../input/findESLintConfiguration"; import { ESLintRuleOptions } from "../../rules/types"; -import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; +import { removeAllExtendsDuplicatedRules } from "./removeAllExtendsDuplicatedRules"; const prepareTestRule = ( ruleOptions: Partial, @@ -32,7 +32,7 @@ const prepareTestRule = ( return { ruleName, allRules, extensions }; }; -describe("removeExtendsDuplicatedRules", () => { +describe("removeAllExtendsDuplicatedRules", () => { it("keeps a rule when there are no rules in the extension", () => { // Arrange const { allRules } = prepareTestRule( @@ -43,7 +43,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, [{}]); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, [{}]); // Assert expect(differentRules.size).toBe(1); @@ -59,7 +59,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -75,7 +75,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -91,7 +91,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -107,7 +107,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -123,7 +123,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -140,7 +140,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -157,7 +157,7 @@ describe("removeExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); diff --git a/src/creation/summarization/removeExtendsDuplicatedRules.ts b/src/creation/pruning/removeAllExtendsDuplicatedRules.ts similarity index 60% rename from src/creation/summarization/removeExtendsDuplicatedRules.ts rename to src/creation/pruning/removeAllExtendsDuplicatedRules.ts index 19361b4f9..c45fbbd8a 100644 --- a/src/creation/summarization/removeExtendsDuplicatedRules.ts +++ b/src/creation/pruning/removeAllExtendsDuplicatedRules.ts @@ -1,24 +1,17 @@ -import { isDeepStrictEqual } from "util"; - import { ESLintConfiguration, ESLintConfigurationRuleValue, } from "../../input/findESLintConfiguration"; -import { convertRawESLintRuleSeverity } from "../../rules/convertRuleSeverity"; +import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; import { ESLintRuleOptions } from "../../rules/types"; +import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; -export const removeExtendsDuplicatedRules = ( +export const removeAllExtendsDuplicatedRules = ( allRules: Map, extensions: Partial[], ) => { - const differentRules = new Map(); const extensionRules = mergeExtensions(extensions); - - for (const [ruleName, value] of allRules) { - if (ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { - differentRules.set(ruleName, value); - } - } + const differentRules = removeExtendsDuplicatedRules(allRules, extensionRules); return { differentRules, extensionRules }; }; @@ -65,23 +58,3 @@ const formatRuleArguments = ( ruleSeverity: convertRawESLintRuleSeverity(originalValue[0]), }; }; - -const ruleValuesAreTheSame = ( - configurationValue: ESLintRuleOptions, - extensionValue: ESLintRuleOptions | undefined, -) => { - return ( - extensionValue !== undefined && - configurationValue.ruleSeverity === extensionValue.ruleSeverity && - isDeepStrictEqual( - { - ruleArguments: [], - ...configurationValue.ruleArguments, - }, - { - ruleArguments: [], - ...extensionValue.ruleArguments, - }, - ) - ); -}; diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.ts b/src/creation/pruning/removeExtendsDuplicatedRules.ts new file mode 100644 index 000000000..962baab7a --- /dev/null +++ b/src/creation/pruning/removeExtendsDuplicatedRules.ts @@ -0,0 +1,38 @@ +import { isDeepStrictEqual } from "util"; + +import { ESLintRuleOptions } from "../../rules/types"; + +export const removeExtendsDuplicatedRules = ( + allRules: Map, + extensionRules: Map, +) => { + const differentRules = new Map(); + + for (const [ruleName, value] of allRules) { + if (ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { + differentRules.set(ruleName, value); + } + } + + return differentRules; +}; + +const ruleValuesAreTheSame = ( + configurationValue: ESLintRuleOptions, + extensionValue: ESLintRuleOptions | undefined, +) => { + return ( + extensionValue !== undefined && + configurationValue.ruleSeverity === extensionValue.ruleSeverity && + isDeepStrictEqual( + { + ruleArguments: [], + ...configurationValue.ruleArguments, + }, + { + ruleArguments: [], + ...extensionValue.ruleArguments, + }, + ) + ); +}; diff --git a/src/creation/summarization/summarizePackageRules.test.ts b/src/creation/summarization/summarizePackageRules.test.ts index bb8d4a835..629b880da 100644 --- a/src/creation/summarization/summarizePackageRules.test.ts +++ b/src/creation/summarization/summarizePackageRules.test.ts @@ -5,7 +5,7 @@ import { summarizePackageRules, SummarizePackageRulesDependencies } from "./summ const createStubDependencies = (overrides: Partial = {}) => ({ addPrettierExtensions: jest.fn(), - removeExtendsDuplicatedRules: jest.fn(), + removeAllExtendsDuplicatedRules: jest.fn(), retrieveExtendsValues: async () => ({ configurationErrors: [], importedExtensions: [], @@ -106,7 +106,7 @@ describe("summarizePackageRules", () => { ]); const extensionRules = new Map(differentRules); const dependencies = createStubDependencies({ - removeExtendsDuplicatedRules: () => ({ differentRules, extensionRules }), + removeAllExtendsDuplicatedRules: () => ({ differentRules, extensionRules }), retrieveExtendsValues: async () => ({ configurationErrors, importedExtensions: [], diff --git a/src/creation/summarization/summarizePackageRules.ts b/src/creation/summarization/summarizePackageRules.ts index 48d737bdf..285d38c6d 100644 --- a/src/creation/summarization/summarizePackageRules.ts +++ b/src/creation/summarization/summarizePackageRules.ts @@ -4,15 +4,15 @@ import { OriginalConfigurations } from "../../input/findOriginalConfigurations"; import { TSLintConfiguration } from "../../input/findTSLintConfiguration"; import { RuleConversionResults } from "../../rules/convertRules"; import { uniqueFromSources } from "../../utils"; +import { removeAllExtendsDuplicatedRules } from "../pruning/removeAllExtendsDuplicatedRules"; import { collectTSLintRulesets } from "./collectTSLintRulesets"; import { addPrettierExtensions } from "./prettier/addPrettierExtensions"; -import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; import { retrieveExtendsValues } from "./retrieveExtendsValues"; import { SummarizedResultsConfiguration } from "./types"; export type SummarizePackageRulesDependencies = { addPrettierExtensions: typeof addPrettierExtensions; - removeExtendsDuplicatedRules: typeof removeExtendsDuplicatedRules; + removeAllExtendsDuplicatedRules: typeof removeAllExtendsDuplicatedRules; retrieveExtendsValues: SansDependencies; }; @@ -48,7 +48,7 @@ export const summarizePackageRules = async ( uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets), ); - const deduplication = dependencies.removeExtendsDuplicatedRules( + const deduplication = dependencies.removeAllExtendsDuplicatedRules( ruleConversionResults.converted, importedExtensions, ); diff --git a/src/creation/writeConversionResults.ts b/src/creation/writeConversionResults.ts index acd1e76a5..1d913e1f2 100644 --- a/src/creation/writeConversionResults.ts +++ b/src/creation/writeConversionResults.ts @@ -1,6 +1,7 @@ import { FileSystem } from "../adapters/fileSystem"; import { AllOriginalConfigurations } from "../input/findOriginalConfigurations"; import { createEnv } from "./eslint/createEnv"; +import { trimESLintRules } from "./eslint/trimESLintRules"; import { formatConvertedRules } from "./formatConvertedRules"; import { formatOutput } from "./formatting/formatOutput"; import { SummarizedResultsConfiguration } from "./summarization/types"; @@ -34,7 +35,7 @@ export const writeConversionResults = async ( }, plugins, rules: { - ...formatESLintRules(eslint?.full.rules, summarizedResults), + ...trimESLintRules(eslint?.full.rules, summarizedResults.extensionRules), ...formatConvertedRules(summarizedResults, tslint.full), }, }; diff --git a/src/input/findESLintConfiguration.ts b/src/input/findESLintConfiguration.ts index f066520cf..2c2f6356d 100644 --- a/src/input/findESLintConfiguration.ts +++ b/src/input/findESLintConfiguration.ts @@ -1,6 +1,6 @@ import { Exec } from "../adapters/exec"; import { SansDependencies } from "../binding"; -import { ESLintRuleSeverity } from "../rules/types"; +import { RawESLintRuleSeverity } from "../rules/types"; import { TSLintToESLintSettings } from "../types"; import { uniqueFromSources } from "../utils"; import { findRawConfiguration } from "./findRawConfiguration"; @@ -19,12 +19,7 @@ export type ESLintConfigurationRules = { [i: string]: ESLintConfigurationRuleValue; }; -export type ESLintConfigurationRuleValue = - | 0 - | 1 - | 2 - | ESLintRuleSeverity - | [ESLintRuleSeverity, any]; +export type ESLintConfigurationRuleValue = RawESLintRuleSeverity | [RawESLintRuleSeverity, any]; const defaultESLintConfiguration = { env: {}, diff --git a/src/rules/convertRuleSeverity.ts b/src/rules/convertRuleSeverity.ts deleted file mode 100644 index 861a1eab4..000000000 --- a/src/rules/convertRuleSeverity.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ESLintRuleSeverity, TSLintRuleSeverity } from "./types"; - -/** - * Converts a TSLint rule severity string to the ESLint equivalent. - */ -export const convertTSLintRuleSeverity = ( - tslintSeverity: TSLintRuleSeverity, -): ESLintRuleSeverity => { - return tslintSeverity === "warning" ? "warn" : tslintSeverity; -}; - -export const convertRawESLintRuleSeverity = ( - rawSeverity: 0 | 1 | 2 | ESLintRuleSeverity, -): ESLintRuleSeverity => { - switch (rawSeverity) { - case 0: - return "off"; - - case 1: - return "warn"; - - case 2: - return "error"; - - default: - return rawSeverity; - } -}; diff --git a/src/rules/convertRules.ts b/src/rules/convertRules.ts index 0440bfcf6..e4a77816c 100644 --- a/src/rules/convertRules.ts +++ b/src/rules/convertRules.ts @@ -3,8 +3,8 @@ import { ErrorSummary } from "../errors/errorSummary"; import { TSLintConfigurationRules } from "../input/findTSLintConfiguration"; import { RuleConverter } from "./converter"; import { convertRule } from "./convertRule"; -import { convertTSLintRuleSeverity } from "./convertRuleSeverity"; -import { formatRawTslintRule } from "./formatRawTslintRule"; +import { convertTSLintRuleSeverity } from "./formats/convertTSLintRuleSeverity"; +import { formatRawTslintRule } from "./formats/formatRawTslintRule"; import { RuleMerger } from "./merger"; import { TSLintRuleOptions, ESLintRuleOptions } from "./types"; diff --git a/src/rules/formatRawTslintRule.test.ts b/src/rules/formatRawTslintRule.test.ts index 2dd8f06d5..cc85a81ad 100644 --- a/src/rules/formatRawTslintRule.test.ts +++ b/src/rules/formatRawTslintRule.test.ts @@ -1,4 +1,4 @@ -import { formatRawTslintRule } from "./formatRawTslintRule"; +import { formatRawTslintRule } from "./formats/formatRawTslintRule"; describe("formatRawTslintRule", () => { it("supplies default values when none are provided", () => { diff --git a/src/rules/convertRuleSeverity.test.ts b/src/rules/formats/convertRuleSeverity.test.ts similarity index 52% rename from src/rules/convertRuleSeverity.test.ts rename to src/rules/formats/convertRuleSeverity.test.ts index 2297e7bc8..8e42d5101 100644 --- a/src/rules/convertRuleSeverity.test.ts +++ b/src/rules/formats/convertRuleSeverity.test.ts @@ -1,39 +1,4 @@ -import { convertTSLintRuleSeverity, convertRawESLintRuleSeverity } from "./convertRuleSeverity"; - -describe("convertRuleSeverity", () => { - it("returns error when the severity is error", () => { - // Arrange - const tslintSeverity = "error"; - - // Act - const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); - - // Assert - expect(eslintSeverity).toEqual("error"); - }); - - it("returns off when the severity is off", () => { - // Arrange - const tslintSeverity = "off"; - - // Act - const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); - - // Assert - expect(eslintSeverity).toEqual("off"); - }); - - it("returns warn when the severity is warning", () => { - // Arrange - const tslintSeverity = "warning"; - - // Act - const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); - - // Assert - expect(eslintSeverity).toEqual("warn"); - }); -}); +import { convertRawESLintRuleSeverity } from "./convertRuleSeverity"; describe("convertRawESLintRuleSeverity", () => { it("returns off when the severity is 0", () => { diff --git a/src/rules/formats/convertRuleSeverity.ts b/src/rules/formats/convertRuleSeverity.ts new file mode 100644 index 000000000..9db517d02 --- /dev/null +++ b/src/rules/formats/convertRuleSeverity.ts @@ -0,0 +1,19 @@ +import { ESLintRuleSeverity, RawESLintRuleSeverity } from "../types"; + +export const convertRawESLintRuleSeverity = ( + rawSeverity: RawESLintRuleSeverity, +): ESLintRuleSeverity => { + switch (rawSeverity) { + case 0: + return "off"; + + case 1: + return "warn"; + + case 2: + return "error"; + + default: + return rawSeverity; + } +}; diff --git a/src/rules/formats/convertTSLintRuleSeverity.test.ts b/src/rules/formats/convertTSLintRuleSeverity.test.ts new file mode 100644 index 000000000..5f0bca3e8 --- /dev/null +++ b/src/rules/formats/convertTSLintRuleSeverity.test.ts @@ -0,0 +1,36 @@ +import { convertTSLintRuleSeverity } from "./convertTSLintRuleSeverity"; + +describe("convertRuleSeverity", () => { + it("returns error when the severity is error", () => { + // Arrange + const tslintSeverity = "error"; + + // Act + const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); + + // Assert + expect(eslintSeverity).toEqual("error"); + }); + + it("returns off when the severity is off", () => { + // Arrange + const tslintSeverity = "off"; + + // Act + const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); + + // Assert + expect(eslintSeverity).toEqual("off"); + }); + + it("returns warn when the severity is warning", () => { + // Arrange + const tslintSeverity = "warning"; + + // Act + const eslintSeverity = convertTSLintRuleSeverity(tslintSeverity); + + // Assert + expect(eslintSeverity).toEqual("warn"); + }); +}); diff --git a/src/rules/formats/convertTSLintRuleSeverity.ts b/src/rules/formats/convertTSLintRuleSeverity.ts new file mode 100644 index 000000000..f13856402 --- /dev/null +++ b/src/rules/formats/convertTSLintRuleSeverity.ts @@ -0,0 +1,10 @@ +import { ESLintRuleSeverity, TSLintRuleSeverity } from "../types"; + +/** + * Converts a TSLint rule severity string to the ESLint equivalent. + */ +export const convertTSLintRuleSeverity = ( + tslintSeverity: TSLintRuleSeverity, +): ESLintRuleSeverity => { + return tslintSeverity === "warning" ? "warn" : tslintSeverity; +}; diff --git a/src/rules/formats/formatRawESLintRule.ts b/src/rules/formats/formatRawESLintRule.ts new file mode 100644 index 000000000..eb6115e47 --- /dev/null +++ b/src/rules/formats/formatRawESLintRule.ts @@ -0,0 +1,12 @@ +import { ESLintRuleOptions, RawESLintRuleSeverity } from "../types"; +import { convertRawESLintRuleSeverity } from "../formats/convertRuleSeverity"; + +export const formatRawTslintRule = ( + ruleName: string, + severity: RawESLintRuleSeverity, + ...ruleArguments: unknown[] +): ESLintRuleOptions => ({ + ruleName, + ruleArguments, + ruleSeverity: convertRawESLintRuleSeverity(severity), +}); diff --git a/src/rules/formatRawTslintRule.ts b/src/rules/formats/formatRawTslintRule.ts similarity index 81% rename from src/rules/formatRawTslintRule.ts rename to src/rules/formats/formatRawTslintRule.ts index a79211707..c4c7f0f92 100644 --- a/src/rules/formatRawTslintRule.ts +++ b/src/rules/formats/formatRawTslintRule.ts @@ -1,4 +1,4 @@ -import { TSLintRuleOptions } from "./types"; +import { TSLintRuleOptions } from "../types"; export const formatRawTslintRule = ( ruleName: string, diff --git a/src/rules/types.ts b/src/rules/types.ts index 791d59472..6034c49e2 100644 --- a/src/rules/types.ts +++ b/src/rules/types.ts @@ -8,6 +8,8 @@ export type TSLintRuleOptions = { export type ESLintRuleSeverity = "warn" | "error" | "off"; +export type RawESLintRuleSeverity = ESLintRuleSeverity | 0 | 1 | 2; + export type ESLintRuleOptions = { notices?: any[]; ruleArguments?: any[]; diff --git a/src/typings/eslint-config-prettier.d.ts b/src/typings/eslint-config-prettier.d.ts deleted file mode 100644 index 69c1d231b..000000000 --- a/src/typings/eslint-config-prettier.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Pending https://github.com/DefinitelyTyped/DefinitelyTyped/pull/44245... -declare module "eslint-config-prettier" { - export const rules: Record; -} From 99ba0187c751fabcadff09413e56def11f5c7532 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 14:14:17 -0400 Subject: [PATCH 3/7] Moved trimming into the existing summarization section --- docs/Architecture.md | 1 + src/creation/eslint/createEnv.test.ts | 188 ------------------ src/creation/eslint/createEnv.ts | 27 --- src/creation/eslint/trimESLintRules.ts | 26 --- .../summarization/normalizeESLintRules.ts | 20 ++ .../summarization/summarizePackageRules.ts | 13 +- 6 files changed, 30 insertions(+), 245 deletions(-) delete mode 100644 src/creation/eslint/createEnv.test.ts delete mode 100644 src/creation/eslint/createEnv.ts delete mode 100644 src/creation/eslint/trimESLintRules.ts create mode 100644 src/creation/summarization/normalizeESLintRules.ts diff --git a/docs/Architecture.md b/docs/Architecture.md index 660a3f22a..7bd83e8c5 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -15,6 +15,7 @@ Within `src/conversion/convertConfig.ts`, the following steps occur: 2. TSLint rules are converted into their ESLint configurations 3. ESLint configurations are summarized based on extended ESLint and TSLint presets - 3a. If no output rules conflict with `eslint-config-prettier`, it's added in + - 3b. Any ESLint rules that are configured the same as an extended preset are trimmed 4. The summarized configuration is written to the output config file 5. Files to transform comments in have source text rewritten using the same rule conversion logic 6. A summary of the results is printed to the user's console diff --git a/src/creation/eslint/createEnv.test.ts b/src/creation/eslint/createEnv.test.ts deleted file mode 100644 index c648ca567..000000000 --- a/src/creation/eslint/createEnv.test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { createEnv } from "./createEnv"; -import { TypeScriptConfiguration } from "../../input/findTypeScriptConfiguration"; - -const createTypeScriptCompilerOptions = ( - overrides: Partial = {}, -) => ({ - target: "es3", - ...overrides, -}); - -describe("createEnv", () => { - it("returns node, browser, and es6 as true if typescript is undefined", () => { - // Arrange - const packages = undefined; - const typescript = undefined; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - browser: true, - es6: true, - node: true, - }), - ); - }); - - it("returns browser as true if no typescript libs are provided", () => { - // Arrange - const packages = undefined; - const typescript = { - compilerOptions: createTypeScriptCompilerOptions(), - }; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - browser: true, - }), - ); - }); - - it("returns browser as false if typescript libs don't include dom", () => { - // Arrange - const packages = undefined; - const typescript = { - compilerOptions: createTypeScriptCompilerOptions({ - lib: ["esnext"], - }), - }; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).not.toContain({ - browser: expect.any(Boolean), - }); - }); - - it("returns browser as true if a typescript lib is dom", () => { - // Arrange - const packages = undefined; - const typescript = { - compilerOptions: createTypeScriptCompilerOptions({ - lib: ["dom"], - }), - }; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - browser: true, - }), - ); - }); - - it("returns es6 as false if the typescript target is lower than es6", () => { - // Arrange - const packages = undefined; - const typescript = { - compilerOptions: createTypeScriptCompilerOptions({ - target: "es5", - }), - }; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).not.toEqual( - expect.objectContaining({ - es6: expect.any(Boolean), - }), - ); - }); - - it("returns es6 as true if the typescript target includes es6", () => { - // Arrange - const packages = undefined; - const typescript = { - compilerOptions: createTypeScriptCompilerOptions({ - target: "es2015", - }), - }; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - es6: true, - }), - ); - }); - - it("returns node as false if package dependencies and devDependencies don't include @types/node", () => { - // Arrange - const packages = { - dependencies: {}, - devDependencies: { - "@types/other": "1.2.3", - }, - }; - const typescript = undefined; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).not.toEqual( - expect.objectContaining({ - node: expect.any(Boolean), - }), - ); - }); - - it("returns node as true if package dependencies include @types/node", () => { - // Arrange - const packages = { - dependencies: { - "@types/node": "1.2.3", - }, - devDependencies: {}, - }; - const typescript = undefined; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - node: true, - }), - ); - }); - - it("returns node as true if package devDependencies include @types/node", () => { - // Arrange - const packages = { - dependencies: {}, - devDependencies: { - "@types/node": "1.2.3", - }, - }; - const typescript = undefined; - - // Act - const env = createEnv({ packages, typescript }); - - // Assert - expect(env).toEqual( - expect.objectContaining({ - node: true, - }), - ); - }); -}); diff --git a/src/creation/eslint/createEnv.ts b/src/creation/eslint/createEnv.ts deleted file mode 100644 index a02b617da..000000000 --- a/src/creation/eslint/createEnv.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { AllOriginalConfigurations } from "../../input/findOriginalConfigurations"; - -export const createEnv = ({ - packages, - typescript, -}: Pick) => { - const browser = - typescript === undefined || - typescript.compilerOptions.lib === undefined || - typescript.compilerOptions.lib.includes("dom"); - - const es6 = - typescript === undefined || - !["es3", "es5"].includes(typescript.compilerOptions.target.toLowerCase()); - - const node = - packages === undefined || - [...Object.keys(packages.dependencies), ...Object.keys(packages.devDependencies)].some( - (dependency) => dependency.toLowerCase() === "@types/node", - ); - - return { - ...(browser && { browser }), - ...(es6 && { es6 }), - ...(node && { node }), - }; -}; diff --git a/src/creation/eslint/trimESLintRules.ts b/src/creation/eslint/trimESLintRules.ts deleted file mode 100644 index f0ee58223..000000000 --- a/src/creation/eslint/trimESLintRules.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ESLintConfigurationRules } from "../../input/findESLintConfiguration"; -import { ESLintRuleOptions } from "../../rules/types"; -import { removeExtendsDuplicatedRules } from "../pruning/removeExtendsDuplicatedRules"; -import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; - -export const trimESLintRules = ( - rules: ESLintConfigurationRules | undefined, - extensionRules: Map, -) => { - if (rules === undefined) { - return undefined; - } - - const parsedRules = Object.entries(rules).map(([ruleName, configuration]): [ - string, - ESLintRuleOptions, - ] => { - const [rawRuleSeverity, ruleArguments] = - configuration instanceof Array ? configuration : [configuration, {}]; - const ruleSeverity = convertRawESLintRuleSeverity(rawRuleSeverity); - - return [ruleName, { ruleArguments, ruleName, ruleSeverity }]; - }); - - return removeExtendsDuplicatedRules(new Map(parsedRules), extensionRules); -}; diff --git a/src/creation/summarization/normalizeESLintRules.ts b/src/creation/summarization/normalizeESLintRules.ts new file mode 100644 index 000000000..33a56e100 --- /dev/null +++ b/src/creation/summarization/normalizeESLintRules.ts @@ -0,0 +1,20 @@ +import { ESLintConfigurationRules } from "../../input/findESLintConfiguration"; +import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; +import { ESLintRuleOptions } from "../../rules/types"; + +/** + * Normalizes raw ESLint rule configurations into our standardized output format. + */ +export const normalizeESLintRules = (userRules: ESLintConfigurationRules | undefined) => { + const output: Map = new Map(); + + for (const [ruleName, configuration] of Object.entries(userRules ?? {})) { + const [rawRuleSeverity, ruleArguments] = + configuration instanceof Array ? configuration : [configuration, {}]; + const ruleSeverity = convertRawESLintRuleSeverity(rawRuleSeverity); + + output.set(ruleName, { ruleArguments, ruleName, ruleSeverity }); + } + + return output; +}; diff --git a/src/creation/summarization/summarizePackageRules.ts b/src/creation/summarization/summarizePackageRules.ts index 285d38c6d..030afc03a 100644 --- a/src/creation/summarization/summarizePackageRules.ts +++ b/src/creation/summarization/summarizePackageRules.ts @@ -9,6 +9,7 @@ import { collectTSLintRulesets } from "./collectTSLintRulesets"; import { addPrettierExtensions } from "./prettier/addPrettierExtensions"; import { retrieveExtendsValues } from "./retrieveExtendsValues"; import { SummarizedResultsConfiguration } from "./types"; +import { normalizeESLintRules } from "./normalizeESLintRules"; export type SummarizePackageRulesDependencies = { addPrettierExtensions: typeof addPrettierExtensions; @@ -48,16 +49,20 @@ export const summarizePackageRules = async ( uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets), ); - const deduplication = dependencies.removeAllExtendsDuplicatedRules( - ruleConversionResults.converted, + // 3b. Any ESLint rules that are configured the same as an extended preset are trimmed + const deduplicated = dependencies.removeAllExtendsDuplicatedRules( + new Map([ + ...Array.from(ruleConversionResults.converted), + ...Array.from(normalizeESLintRules(eslint?.full.rules)), + ]), importedExtensions, ); return { ...ruleConversionResults, - converted: deduplication.differentRules, + converted: deduplicated.differentRules, extends: uniqueFromSources(allExtensions), - extensionRules: deduplication.extensionRules, + extensionRules: deduplicated.extensionRules, failed: [...ruleConversionResults.failed, ...configurationErrors], }; }; From 26a60195782918946e1c9f4fa6f9f3fe59a993ab Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 14:42:39 -0400 Subject: [PATCH 4/7] Reverted some unnecessary changes --- package-lock.json | 6 - package.json | 1 - src/cli/main.ts | 4 +- src/creation/eslint/createEnv.test.ts | 188 ++++++++++++++++++ src/creation/eslint/createEnv.ts | 27 +++ .../removeAllExtendsDuplicatedRules.ts | 60 ------ ...s => removeExtendsDuplicatedRules.test.ts} | 20 +- .../pruning/removeExtendsDuplicatedRules.ts | 68 ++++++- .../summarizePackageRules.test.ts | 4 +- .../summarization/summarizePackageRules.ts | 11 +- src/creation/writeConversionResults.ts | 3 +- src/typings/eslint-config-prettier.d.ts | 4 + 12 files changed, 296 insertions(+), 100 deletions(-) create mode 100644 src/creation/eslint/createEnv.test.ts create mode 100644 src/creation/eslint/createEnv.ts delete mode 100644 src/creation/pruning/removeAllExtendsDuplicatedRules.ts rename src/creation/pruning/{removeAllExtendsDuplicatedRules.test.ts => removeExtendsDuplicatedRules.test.ts} (81%) create mode 100644 src/typings/eslint-config-prettier.d.ts diff --git a/package-lock.json b/package-lock.json index 5ef8ccfae..7dd553e55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3063,12 +3063,6 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, - "@types/eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@types/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-UBuZMZVog9c9jXvArbYtWH570sRWNaU6kEnUAHsHb/+zAufzPT4I+gMkUR2dVPWlqiceoRU1thjUVdGrAWVpCA==", - "dev": true - }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", diff --git a/package.json b/package.json index 8d7410fde..a5635a81a 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "@babel/plugin-proposal-optional-chaining": "7.9.0", "@babel/preset-env": "7.9.6", "@babel/preset-typescript": "7.9.0", - "@types/eslint-config-prettier": "^6.11.0", "@types/glob": "7.1.1", "@types/jest": "25.2.1", "@types/node": "12.12.21", diff --git a/src/cli/main.ts b/src/cli/main.ts index 2e4d536f0..d01b14f45 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -16,7 +16,7 @@ import { convertEditorConfig, ConvertEditorConfigDependencies, } from "../conversion/convertEditorConfig"; -import { removeAllExtendsDuplicatedRules } from "../creation/pruning/removeAllExtendsDuplicatedRules"; +import { removeExtendsDuplicatedRules } from "../creation/pruning/removeExtendsDuplicatedRules"; import { addPrettierExtensions } from "../creation/summarization/prettier/addPrettierExtensions"; import { retrieveExtendsValues, @@ -140,7 +140,7 @@ const retrieveExtendsValuesDependencies: RetrieveExtendsValuesDependencies = { const summarizePackageRulesDependencies: SummarizePackageRulesDependencies = { addPrettierExtensions, - removeAllExtendsDuplicatedRules, + removeExtendsDuplicatedRules, retrieveExtendsValues: bind(retrieveExtendsValues, retrieveExtendsValuesDependencies), }; diff --git a/src/creation/eslint/createEnv.test.ts b/src/creation/eslint/createEnv.test.ts new file mode 100644 index 000000000..c648ca567 --- /dev/null +++ b/src/creation/eslint/createEnv.test.ts @@ -0,0 +1,188 @@ +import { createEnv } from "./createEnv"; +import { TypeScriptConfiguration } from "../../input/findTypeScriptConfiguration"; + +const createTypeScriptCompilerOptions = ( + overrides: Partial = {}, +) => ({ + target: "es3", + ...overrides, +}); + +describe("createEnv", () => { + it("returns node, browser, and es6 as true if typescript is undefined", () => { + // Arrange + const packages = undefined; + const typescript = undefined; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + browser: true, + es6: true, + node: true, + }), + ); + }); + + it("returns browser as true if no typescript libs are provided", () => { + // Arrange + const packages = undefined; + const typescript = { + compilerOptions: createTypeScriptCompilerOptions(), + }; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + browser: true, + }), + ); + }); + + it("returns browser as false if typescript libs don't include dom", () => { + // Arrange + const packages = undefined; + const typescript = { + compilerOptions: createTypeScriptCompilerOptions({ + lib: ["esnext"], + }), + }; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).not.toContain({ + browser: expect.any(Boolean), + }); + }); + + it("returns browser as true if a typescript lib is dom", () => { + // Arrange + const packages = undefined; + const typescript = { + compilerOptions: createTypeScriptCompilerOptions({ + lib: ["dom"], + }), + }; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + browser: true, + }), + ); + }); + + it("returns es6 as false if the typescript target is lower than es6", () => { + // Arrange + const packages = undefined; + const typescript = { + compilerOptions: createTypeScriptCompilerOptions({ + target: "es5", + }), + }; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).not.toEqual( + expect.objectContaining({ + es6: expect.any(Boolean), + }), + ); + }); + + it("returns es6 as true if the typescript target includes es6", () => { + // Arrange + const packages = undefined; + const typescript = { + compilerOptions: createTypeScriptCompilerOptions({ + target: "es2015", + }), + }; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + es6: true, + }), + ); + }); + + it("returns node as false if package dependencies and devDependencies don't include @types/node", () => { + // Arrange + const packages = { + dependencies: {}, + devDependencies: { + "@types/other": "1.2.3", + }, + }; + const typescript = undefined; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).not.toEqual( + expect.objectContaining({ + node: expect.any(Boolean), + }), + ); + }); + + it("returns node as true if package dependencies include @types/node", () => { + // Arrange + const packages = { + dependencies: { + "@types/node": "1.2.3", + }, + devDependencies: {}, + }; + const typescript = undefined; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + node: true, + }), + ); + }); + + it("returns node as true if package devDependencies include @types/node", () => { + // Arrange + const packages = { + dependencies: {}, + devDependencies: { + "@types/node": "1.2.3", + }, + }; + const typescript = undefined; + + // Act + const env = createEnv({ packages, typescript }); + + // Assert + expect(env).toEqual( + expect.objectContaining({ + node: true, + }), + ); + }); +}); diff --git a/src/creation/eslint/createEnv.ts b/src/creation/eslint/createEnv.ts new file mode 100644 index 000000000..a02b617da --- /dev/null +++ b/src/creation/eslint/createEnv.ts @@ -0,0 +1,27 @@ +import { AllOriginalConfigurations } from "../../input/findOriginalConfigurations"; + +export const createEnv = ({ + packages, + typescript, +}: Pick) => { + const browser = + typescript === undefined || + typescript.compilerOptions.lib === undefined || + typescript.compilerOptions.lib.includes("dom"); + + const es6 = + typescript === undefined || + !["es3", "es5"].includes(typescript.compilerOptions.target.toLowerCase()); + + const node = + packages === undefined || + [...Object.keys(packages.dependencies), ...Object.keys(packages.devDependencies)].some( + (dependency) => dependency.toLowerCase() === "@types/node", + ); + + return { + ...(browser && { browser }), + ...(es6 && { es6 }), + ...(node && { node }), + }; +}; diff --git a/src/creation/pruning/removeAllExtendsDuplicatedRules.ts b/src/creation/pruning/removeAllExtendsDuplicatedRules.ts deleted file mode 100644 index c45fbbd8a..000000000 --- a/src/creation/pruning/removeAllExtendsDuplicatedRules.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { - ESLintConfiguration, - ESLintConfigurationRuleValue, -} from "../../input/findESLintConfiguration"; -import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; -import { ESLintRuleOptions } from "../../rules/types"; -import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; - -export const removeAllExtendsDuplicatedRules = ( - allRules: Map, - extensions: Partial[], -) => { - const extensionRules = mergeExtensions(extensions); - const differentRules = removeExtendsDuplicatedRules(allRules, extensionRules); - - return { differentRules, extensionRules }; -}; - -const mergeExtensions = (extensions: Partial[]) => { - const mergedRules = new Map(); - - for (const extension of extensions) { - if (extension.rules === undefined) { - continue; - } - - for (const ruleName in extension.rules) { - mergedRules.set(ruleName, formatRuleArguments(ruleName, extension.rules[ruleName])); - } - } - - return mergedRules; -}; - -const formatRuleArguments = ( - ruleName: string, - originalValue: ESLintConfigurationRuleValue, -): ESLintRuleOptions => { - if (typeof originalValue === "number") { - return { - ruleArguments: [], - ruleName, - ruleSeverity: convertRawESLintRuleSeverity(originalValue), - }; - } - - if (typeof originalValue === "string") { - return { - ruleArguments: [], - ruleName, - ruleSeverity: originalValue, - }; - } - - return { - ruleArguments: originalValue.slice(1), - ruleName, - ruleSeverity: convertRawESLintRuleSeverity(originalValue[0]), - }; -}; diff --git a/src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts similarity index 81% rename from src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts rename to src/creation/pruning/removeExtendsDuplicatedRules.test.ts index 3265f0217..f104966c0 100644 --- a/src/creation/pruning/removeAllExtendsDuplicatedRules.test.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts @@ -3,7 +3,7 @@ import { ESLintConfigurationRuleValue, } from "../../input/findESLintConfiguration"; import { ESLintRuleOptions } from "../../rules/types"; -import { removeAllExtendsDuplicatedRules } from "./removeAllExtendsDuplicatedRules"; +import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; const prepareTestRule = ( ruleOptions: Partial, @@ -32,7 +32,7 @@ const prepareTestRule = ( return { ruleName, allRules, extensions }; }; -describe("removeAllExtendsDuplicatedRules", () => { +describe("removeExtendsDuplicatedRules", () => { it("keeps a rule when there are no rules in the extension", () => { // Arrange const { allRules } = prepareTestRule( @@ -43,7 +43,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, [{}]); + const { differentRules } = removeExtendsDuplicatedRules(allRules, [{}]); // Assert expect(differentRules.size).toBe(1); @@ -59,7 +59,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -75,7 +75,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -91,7 +91,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -107,7 +107,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -123,7 +123,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); @@ -140,7 +140,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(0); @@ -157,7 +157,7 @@ describe("removeAllExtendsDuplicatedRules", () => { ); // Act - const { differentRules } = removeAllExtendsDuplicatedRules(allRules, extensions); + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert expect(differentRules.size).toBe(1); diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.ts b/src/creation/pruning/removeExtendsDuplicatedRules.ts index 962baab7a..16af01b6a 100644 --- a/src/creation/pruning/removeExtendsDuplicatedRules.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.ts @@ -1,20 +1,72 @@ import { isDeepStrictEqual } from "util"; +import { + ESLintConfiguration, + ESLintConfigurationRuleValue, +} from "../../input/findESLintConfiguration"; +import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; import { ESLintRuleOptions } from "../../rules/types"; +/** + * Finds the ESLint rules that aren't configured the same as their last preset + */ export const removeExtendsDuplicatedRules = ( allRules: Map, - extensionRules: Map, + extensions: Partial[], ) => { const differentRules = new Map(); + const extensionRules = mergeExtensions(extensions); for (const [ruleName, value] of allRules) { - if (ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { + if (!ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { differentRules.set(ruleName, value); } } - return differentRules; + return { differentRules, extensionRules }; +}; + +const mergeExtensions = (extensions: Partial[]) => { + const mergedRules = new Map(); + + for (const extension of extensions) { + if (extension.rules === undefined) { + continue; + } + + for (const ruleName in extension.rules ?? {}) { + mergedRules.set(ruleName, formatRuleArguments(ruleName, extension.rules[ruleName])); + } + } + + return mergedRules; +}; + +const formatRuleArguments = ( + ruleName: string, + originalValue: ESLintConfigurationRuleValue, +): ESLintRuleOptions => { + if (typeof originalValue === "number") { + return { + ruleArguments: [], + ruleName, + ruleSeverity: convertRawESLintRuleSeverity(originalValue), + }; + } + + if (typeof originalValue === "string") { + return { + ruleArguments: [], + ruleName, + ruleSeverity: originalValue, + }; + } + + return { + ruleArguments: originalValue.slice(1), + ruleName, + ruleSeverity: convertRawESLintRuleSeverity(originalValue[0]), + }; }; const ruleValuesAreTheSame = ( @@ -25,14 +77,8 @@ const ruleValuesAreTheSame = ( extensionValue !== undefined && configurationValue.ruleSeverity === extensionValue.ruleSeverity && isDeepStrictEqual( - { - ruleArguments: [], - ...configurationValue.ruleArguments, - }, - { - ruleArguments: [], - ...extensionValue.ruleArguments, - }, + configurationValue.ruleArguments ?? [], + extensionValue.ruleArguments ?? [], ) ); }; diff --git a/src/creation/summarization/summarizePackageRules.test.ts b/src/creation/summarization/summarizePackageRules.test.ts index 629b880da..bb8d4a835 100644 --- a/src/creation/summarization/summarizePackageRules.test.ts +++ b/src/creation/summarization/summarizePackageRules.test.ts @@ -5,7 +5,7 @@ import { summarizePackageRules, SummarizePackageRulesDependencies } from "./summ const createStubDependencies = (overrides: Partial = {}) => ({ addPrettierExtensions: jest.fn(), - removeAllExtendsDuplicatedRules: jest.fn(), + removeExtendsDuplicatedRules: jest.fn(), retrieveExtendsValues: async () => ({ configurationErrors: [], importedExtensions: [], @@ -106,7 +106,7 @@ describe("summarizePackageRules", () => { ]); const extensionRules = new Map(differentRules); const dependencies = createStubDependencies({ - removeAllExtendsDuplicatedRules: () => ({ differentRules, extensionRules }), + removeExtendsDuplicatedRules: () => ({ differentRules, extensionRules }), retrieveExtendsValues: async () => ({ configurationErrors, importedExtensions: [], diff --git a/src/creation/summarization/summarizePackageRules.ts b/src/creation/summarization/summarizePackageRules.ts index 030afc03a..10a024f9a 100644 --- a/src/creation/summarization/summarizePackageRules.ts +++ b/src/creation/summarization/summarizePackageRules.ts @@ -4,7 +4,7 @@ import { OriginalConfigurations } from "../../input/findOriginalConfigurations"; import { TSLintConfiguration } from "../../input/findTSLintConfiguration"; import { RuleConversionResults } from "../../rules/convertRules"; import { uniqueFromSources } from "../../utils"; -import { removeAllExtendsDuplicatedRules } from "../pruning/removeAllExtendsDuplicatedRules"; +import { removeExtendsDuplicatedRules } from "../pruning/removeExtendsDuplicatedRules"; import { collectTSLintRulesets } from "./collectTSLintRulesets"; import { addPrettierExtensions } from "./prettier/addPrettierExtensions"; import { retrieveExtendsValues } from "./retrieveExtendsValues"; @@ -13,7 +13,7 @@ import { normalizeESLintRules } from "./normalizeESLintRules"; export type SummarizePackageRulesDependencies = { addPrettierExtensions: typeof addPrettierExtensions; - removeAllExtendsDuplicatedRules: typeof removeAllExtendsDuplicatedRules; + removeExtendsDuplicatedRules: typeof removeExtendsDuplicatedRules; retrieveExtendsValues: SansDependencies; }; @@ -45,15 +45,14 @@ export const summarizePackageRules = async ( }; } + // 3b. Any ESLint rules that are configured the same as an extended preset are trimmed const { configurationErrors, importedExtensions } = await dependencies.retrieveExtendsValues( uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets), ); - - // 3b. Any ESLint rules that are configured the same as an extended preset are trimmed - const deduplicated = dependencies.removeAllExtendsDuplicatedRules( + const deduplicated = dependencies.removeExtendsDuplicatedRules( new Map([ - ...Array.from(ruleConversionResults.converted), ...Array.from(normalizeESLintRules(eslint?.full.rules)), + ...Array.from(ruleConversionResults.converted), ]), importedExtensions, ); diff --git a/src/creation/writeConversionResults.ts b/src/creation/writeConversionResults.ts index 1d913e1f2..3bca7a40f 100644 --- a/src/creation/writeConversionResults.ts +++ b/src/creation/writeConversionResults.ts @@ -1,7 +1,6 @@ import { FileSystem } from "../adapters/fileSystem"; import { AllOriginalConfigurations } from "../input/findOriginalConfigurations"; import { createEnv } from "./eslint/createEnv"; -import { trimESLintRules } from "./eslint/trimESLintRules"; import { formatConvertedRules } from "./formatConvertedRules"; import { formatOutput } from "./formatting/formatOutput"; import { SummarizedResultsConfiguration } from "./summarization/types"; @@ -35,7 +34,7 @@ export const writeConversionResults = async ( }, plugins, rules: { - ...trimESLintRules(eslint?.full.rules, summarizedResults.extensionRules), + // ...trimESLintRules(eslint?.full.rules, summarizedResults.extensionRules), ...formatConvertedRules(summarizedResults, tslint.full), }, }; diff --git a/src/typings/eslint-config-prettier.d.ts b/src/typings/eslint-config-prettier.d.ts new file mode 100644 index 000000000..69c1d231b --- /dev/null +++ b/src/typings/eslint-config-prettier.d.ts @@ -0,0 +1,4 @@ +// Pending https://github.com/DefinitelyTyped/DefinitelyTyped/pull/44245... +declare module "eslint-config-prettier" { + export const rules: Record; +} From fcd07615f836c85de852b171c1804ec9433675dc Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 16:19:21 -0400 Subject: [PATCH 5/7] Fixed up edge cases --- src/cli/main.ts | 2 +- .../removeExtendsDuplicatedRules.test.ts | 36 +++++++++- .../pruning/removeExtendsDuplicatedRules.ts | 15 ++--- .../normalizeESLintRules.test.ts | 65 +++++++++++++++++++ .../summarizePackageRules.test.ts | 21 ++++-- src/creation/writeConversionResults.ts | 2 +- src/input/findESLintConfiguration.ts | 5 +- src/rules/formats/formatRawESLintRule.ts | 12 ---- src/rules/types.ts | 4 ++ 9 files changed, 133 insertions(+), 29 deletions(-) create mode 100644 src/creation/summarization/normalizeESLintRules.test.ts delete mode 100644 src/rules/formats/formatRawESLintRule.ts diff --git a/src/cli/main.ts b/src/cli/main.ts index d01b14f45..9b3030afa 100644 --- a/src/cli/main.ts +++ b/src/cli/main.ts @@ -16,8 +16,8 @@ import { convertEditorConfig, ConvertEditorConfigDependencies, } from "../conversion/convertEditorConfig"; -import { removeExtendsDuplicatedRules } from "../creation/pruning/removeExtendsDuplicatedRules"; import { addPrettierExtensions } from "../creation/summarization/prettier/addPrettierExtensions"; +import { removeExtendsDuplicatedRules } from "../creation/pruning/removeExtendsDuplicatedRules"; import { retrieveExtendsValues, RetrieveExtendsValuesDependencies, diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.test.ts b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts index f104966c0..f859be0f3 100644 --- a/src/creation/pruning/removeExtendsDuplicatedRules.test.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts @@ -7,7 +7,7 @@ import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; const prepareTestRule = ( ruleOptions: Partial, - extensionConfiguration: ESLintConfigurationRuleValue = 2, + extensionConfiguration: ESLintConfigurationRuleValue, ) => { const ruleName = "rule-a"; const allRules = new Map([ @@ -81,6 +81,40 @@ describe("removeExtendsDuplicatedRules", () => { expect(differentRules.size).toBe(0); }); + it("removes a rule when it has no arguments and matches an extended rule with an empty arguments array", () => { + // Arrange + const { allRules, extensions } = prepareTestRule( + { + ruleArguments: undefined, + ruleSeverity: "error", + }, + ["error"], + ); + + // Act + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // Assert + expect(differentRules.size).toBe(0); + }); + + it("removes a rule when it has an empty arguments array and matches an extended rule with no arguments", () => { + // Arrange + const { allRules, extensions } = prepareTestRule( + { + ruleArguments: [], + ruleSeverity: "error", + }, + ["error"], + ); + + // Act + const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // Assert + expect(differentRules.size).toBe(0); + }); + it("keeps a rule when it conflicts with an existing rule as numbers", () => { // Arrange const { allRules, extensions } = prepareTestRule( diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.ts b/src/creation/pruning/removeExtendsDuplicatedRules.ts index 16af01b6a..3ac4db5f6 100644 --- a/src/creation/pruning/removeExtendsDuplicatedRules.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.ts @@ -5,7 +5,7 @@ import { ESLintConfigurationRuleValue, } from "../../input/findESLintConfiguration"; import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; -import { ESLintRuleOptions } from "../../rules/types"; +import { ESLintRuleOptions, ESLintRuleOptionsWithArguments } from "../../rules/types"; /** * Finds the ESLint rules that aren't configured the same as their last preset @@ -27,14 +27,14 @@ export const removeExtendsDuplicatedRules = ( }; const mergeExtensions = (extensions: Partial[]) => { - const mergedRules = new Map(); + const mergedRules = new Map(); for (const extension of extensions) { if (extension.rules === undefined) { continue; } - for (const ruleName in extension.rules ?? {}) { + for (const ruleName in extension.rules) { mergedRules.set(ruleName, formatRuleArguments(ruleName, extension.rules[ruleName])); } } @@ -45,7 +45,7 @@ const mergeExtensions = (extensions: Partial[]) => { const formatRuleArguments = ( ruleName: string, originalValue: ESLintConfigurationRuleValue, -): ESLintRuleOptions => { +): ESLintRuleOptionsWithArguments => { if (typeof originalValue === "number") { return { ruleArguments: [], @@ -71,14 +71,11 @@ const formatRuleArguments = ( const ruleValuesAreTheSame = ( configurationValue: ESLintRuleOptions, - extensionValue: ESLintRuleOptions | undefined, + extensionValue: ESLintRuleOptionsWithArguments | undefined, ) => { return ( extensionValue !== undefined && configurationValue.ruleSeverity === extensionValue.ruleSeverity && - isDeepStrictEqual( - configurationValue.ruleArguments ?? [], - extensionValue.ruleArguments ?? [], - ) + isDeepStrictEqual(configurationValue.ruleArguments ?? [], extensionValue.ruleArguments) ); }; diff --git a/src/creation/summarization/normalizeESLintRules.test.ts b/src/creation/summarization/normalizeESLintRules.test.ts new file mode 100644 index 000000000..ac793e4f0 --- /dev/null +++ b/src/creation/summarization/normalizeESLintRules.test.ts @@ -0,0 +1,65 @@ +import { ESLintConfigurationRules } from "../../input/findESLintConfiguration"; +import { normalizeESLintRules } from "./normalizeESLintRules"; + +const ruleName = "rule-a"; + +describe("normalizeESLintRules", () => { + it("returns an empty map when there are no user rules", () => { + // Arrange + const userRules = undefined; + + // Act + const result = normalizeESLintRules(userRules); + + // Assert + expect(result).toEqual(new Map()); + }); + + it("converts a rule when given as an array", () => { + // Arrange + const userRules: ESLintConfigurationRules = { + [ruleName]: ["error", {}], + }; + + // Act + const result = normalizeESLintRules(userRules); + + // Assert + expect(result).toEqual( + new Map([ + [ + ruleName, + { + ruleArguments: {}, + ruleName: "rule-a", + ruleSeverity: "error", + }, + ], + ]), + ); + }); + + it("converts a rule when given as a severity level", () => { + // Arrange + const userRules: ESLintConfigurationRules = { + [ruleName]: "error", + }; + + // Act + const result = normalizeESLintRules(userRules); + + // Assert + expect(result).toEqual( + new Map([ + [ + ruleName, + { + ruleArguments: {}, + ruleName: "rule-a", + ruleSeverity: "error", + }, + ], + ]), + ); + }); +}); diff --git a/src/creation/summarization/summarizePackageRules.test.ts b/src/creation/summarization/summarizePackageRules.test.ts index bb8d4a835..e86e8370e 100644 --- a/src/creation/summarization/summarizePackageRules.test.ts +++ b/src/creation/summarization/summarizePackageRules.test.ts @@ -1,11 +1,14 @@ import { ConfigurationError } from "../../errors/configurationError"; -import { ESLintRuleOptions } from "../../rules/types"; +import { ESLintRuleOptionsWithArguments } from "../../rules/types"; import { createEmptyConversionResults } from "../../conversion/conversionResults.stubs"; import { summarizePackageRules, SummarizePackageRulesDependencies } from "./summarizePackageRules"; const createStubDependencies = (overrides: Partial = {}) => ({ addPrettierExtensions: jest.fn(), - removeExtendsDuplicatedRules: jest.fn(), + removeExtendsDuplicatedRules: () => ({ + differentRules: new Map(), + extensionRules: new Map(), + }), retrieveExtendsValues: async () => ({ configurationErrors: [], importedExtensions: [], @@ -67,7 +70,7 @@ describe("summarizePackageRules", () => { // Assert expect(summarizedResults).toEqual({ ...ruleConversionResults, - converted: undefined, + converted: new Map(), extends: ["prettier", "prettier/@typescript-eslint"], }); }); @@ -94,7 +97,7 @@ describe("summarizePackageRules", () => { it("includes deduplicated rules and extension failures when the ESLint configuration extends", async () => { // Arrange const configurationErrors = [new ConfigurationError(new Error("oh no"), "darn")]; - const differentRules = new Map([ + const differentRules = new Map([ [ "rule-name", { @@ -128,6 +131,16 @@ describe("summarizePackageRules", () => { // Assert expect(summarizedResults).toEqual({ ...ruleConversionResults, + extensionRules: new Map([ + [ + "rule-name", + { + ruleArguments: [], + ruleName: "rule-name", + ruleSeverity: "warn", + }, + ], + ]), converted: differentRules, extends: [...eslintExtends], failed: configurationErrors, diff --git a/src/creation/writeConversionResults.ts b/src/creation/writeConversionResults.ts index 3bca7a40f..d1c1c23a8 100644 --- a/src/creation/writeConversionResults.ts +++ b/src/creation/writeConversionResults.ts @@ -26,7 +26,7 @@ export const writeConversionResults = async ( ...eslint?.full, env: createEnv(originalConfigurations), ...(eslint && { globals: eslint.raw.globals }), - ...(summarizedResults.extends && { extends: summarizedResults.extends }), + ...(summarizedResults.extends?.length !== 0 && { extends: summarizedResults.extends }), parser: "@typescript-eslint/parser", parserOptions: { project: "tsconfig.json", diff --git a/src/input/findESLintConfiguration.ts b/src/input/findESLintConfiguration.ts index 2c2f6356d..0442b07a8 100644 --- a/src/input/findESLintConfiguration.ts +++ b/src/input/findESLintConfiguration.ts @@ -19,7 +19,10 @@ export type ESLintConfigurationRules = { [i: string]: ESLintConfigurationRuleValue; }; -export type ESLintConfigurationRuleValue = RawESLintRuleSeverity | [RawESLintRuleSeverity, any]; +export type ESLintConfigurationRuleValue = + | RawESLintRuleSeverity + | [RawESLintRuleSeverity] + | [RawESLintRuleSeverity, any]; const defaultESLintConfiguration = { env: {}, diff --git a/src/rules/formats/formatRawESLintRule.ts b/src/rules/formats/formatRawESLintRule.ts deleted file mode 100644 index eb6115e47..000000000 --- a/src/rules/formats/formatRawESLintRule.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ESLintRuleOptions, RawESLintRuleSeverity } from "../types"; -import { convertRawESLintRuleSeverity } from "../formats/convertRuleSeverity"; - -export const formatRawTslintRule = ( - ruleName: string, - severity: RawESLintRuleSeverity, - ...ruleArguments: unknown[] -): ESLintRuleOptions => ({ - ruleName, - ruleArguments, - ruleSeverity: convertRawESLintRuleSeverity(severity), -}); diff --git a/src/rules/types.ts b/src/rules/types.ts index 6034c49e2..e0016d435 100644 --- a/src/rules/types.ts +++ b/src/rules/types.ts @@ -16,3 +16,7 @@ export type ESLintRuleOptions = { ruleName: string; ruleSeverity: ESLintRuleSeverity; }; + +export type ESLintRuleOptionsWithArguments = ESLintRuleOptions & { + ruleArguments: any[]; +}; From 3a52945277520e741ad1f80ce71768ecf6192715 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 17:17:31 -0400 Subject: [PATCH 6/7] Split extension merging and rule normalization --- .../convertRawESLintRuleSeverity.test.ts} | 2 +- .../pruning/normalizeExtensions.test.ts | 73 +++++ src/creation/pruning/normalizeExtensions.ts | 41 +++ .../normalizeRawESLintRuleSeverity.test.ts | 47 +++ .../normalizeRawESLintRuleSeverity.ts} | 4 +- .../removeExtendsDuplicatedRules.test.ts | 305 ++++++++++++------ .../pruning/removeExtendsDuplicatedRules.ts | 57 +--- .../summarization/summarizePackageRules.ts | 4 +- 8 files changed, 374 insertions(+), 159 deletions(-) rename src/{rules/formats/convertRuleSeverity.test.ts => creation/pruning/convertRawESLintRuleSeverity.test.ts} (92%) create mode 100644 src/creation/pruning/normalizeExtensions.test.ts create mode 100644 src/creation/pruning/normalizeExtensions.ts create mode 100644 src/creation/pruning/normalizeRawESLintRuleSeverity.test.ts rename src/{rules/formats/convertRuleSeverity.ts => creation/pruning/normalizeRawESLintRuleSeverity.ts} (69%) diff --git a/src/rules/formats/convertRuleSeverity.test.ts b/src/creation/pruning/convertRawESLintRuleSeverity.test.ts similarity index 92% rename from src/rules/formats/convertRuleSeverity.test.ts rename to src/creation/pruning/convertRawESLintRuleSeverity.test.ts index 8e42d5101..e820acd17 100644 --- a/src/rules/formats/convertRuleSeverity.test.ts +++ b/src/creation/pruning/convertRawESLintRuleSeverity.test.ts @@ -1,4 +1,4 @@ -import { convertRawESLintRuleSeverity } from "./convertRuleSeverity"; +import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; describe("convertRawESLintRuleSeverity", () => { it("returns off when the severity is 0", () => { diff --git a/src/creation/pruning/normalizeExtensions.test.ts b/src/creation/pruning/normalizeExtensions.test.ts new file mode 100644 index 000000000..93839ff8b --- /dev/null +++ b/src/creation/pruning/normalizeExtensions.test.ts @@ -0,0 +1,73 @@ +import { normalizeExtensions } from "./normalizeExtensions"; +import { ESLintConfigurationRuleValue } from "../../input/findESLintConfiguration"; + +const createStubExtension = (ruleName: string, ruleValue: ESLintConfigurationRuleValue) => { + return { + rules: { + [ruleName]: ruleValue, + }, + }; +}; + +describe("removeExtendsDuplicatedRules", () => { + it("ignores an empty extension", () => { + // Arrange + const extensions = [{}]; + + // Act + const results = normalizeExtensions(extensions); + + // Assert + expect(results).toEqual(new Map()); + }); + + it("overrides a rule's first value when a second extension contains it", () => { + // Arrange + const ruleName = "rule-a"; + const extensions = [ + createStubExtension(ruleName, "error"), + createStubExtension(ruleName, "warn"), + ]; + + // Act + const results = normalizeExtensions(extensions); + + // Assert + expect(results).toEqual( + new Map([ + [ + ruleName, + { + ruleArguments: [], + ruleName, + ruleSeverity: "warn", + }, + ], + ]), + ); + }); + + it("normalizes a configuration when an array", () => { + // Arrange + const ruleName = "rule-a"; + const ruleArgument = { value: true }; + const extensions = [createStubExtension(ruleName, ["error", ruleArgument])]; + + // Act + const results = normalizeExtensions(extensions); + + // Assert + expect(results).toEqual( + new Map([ + [ + ruleName, + { + ruleArguments: [ruleArgument], + ruleName, + ruleSeverity: "error", + }, + ], + ]), + ); + }); +}); diff --git a/src/creation/pruning/normalizeExtensions.ts b/src/creation/pruning/normalizeExtensions.ts new file mode 100644 index 000000000..f3a22b4f0 --- /dev/null +++ b/src/creation/pruning/normalizeExtensions.ts @@ -0,0 +1,41 @@ +import { + ESLintConfiguration, + ESLintConfigurationRuleValue, +} from "../../input/findESLintConfiguration"; +import { ESLintRuleOptionsWithArguments } from "../../rules/types"; +import { normalizeRawESLintRuleSeverity } from "./normalizeRawESLintRuleSeverity"; + +export const normalizeExtensions = (extensions: Partial[]) => { + const mergedRules = new Map(); + + for (const extension of extensions) { + if (extension.rules === undefined) { + continue; + } + + for (const ruleName in extension.rules) { + mergedRules.set(ruleName, formatRuleArguments(ruleName, extension.rules[ruleName])); + } + } + + return mergedRules; +}; + +const formatRuleArguments = ( + ruleName: string, + originalValue: ESLintConfigurationRuleValue, +): ESLintRuleOptionsWithArguments => { + if (originalValue instanceof Array) { + return { + ruleArguments: originalValue.slice(1), + ruleName, + ruleSeverity: normalizeRawESLintRuleSeverity(originalValue[0]), + }; + } + + return { + ruleArguments: [], + ruleName, + ruleSeverity: normalizeRawESLintRuleSeverity(originalValue), + }; +}; diff --git a/src/creation/pruning/normalizeRawESLintRuleSeverity.test.ts b/src/creation/pruning/normalizeRawESLintRuleSeverity.test.ts new file mode 100644 index 000000000..06c98798f --- /dev/null +++ b/src/creation/pruning/normalizeRawESLintRuleSeverity.test.ts @@ -0,0 +1,47 @@ +import { normalizeRawESLintRuleSeverity } from "./normalizeRawESLintRuleSeverity"; + +describe("normalizeRawESLintRuleSeverity", () => { + it("converts the severity to off when equal to 0", () => { + // Arrange + const rawSeverity = 0; + + // Act + const result = normalizeRawESLintRuleSeverity(rawSeverity); + + // Assert + expect(result).toEqual("off"); + }); + + it("converts the severity to warn when equal to 1", () => { + // Arrange + const rawSeverity = 1; + + // Act + const result = normalizeRawESLintRuleSeverity(rawSeverity); + + // Assert + expect(result).toEqual("warn"); + }); + + it("converts the severity to error when equal to 2", () => { + // Arrange + const rawSeverity = 2; + + // Act + const result = normalizeRawESLintRuleSeverity(rawSeverity); + + // Assert + expect(result).toEqual("error"); + }); + + it("returns the same severity when already a string", () => { + // Arrange + const rawSeverity = "error"; + + // Act + const result = normalizeRawESLintRuleSeverity(rawSeverity); + + // Assert + expect(result).toEqual(rawSeverity); + }); +}); diff --git a/src/rules/formats/convertRuleSeverity.ts b/src/creation/pruning/normalizeRawESLintRuleSeverity.ts similarity index 69% rename from src/rules/formats/convertRuleSeverity.ts rename to src/creation/pruning/normalizeRawESLintRuleSeverity.ts index 9db517d02..a3063b5bd 100644 --- a/src/rules/formats/convertRuleSeverity.ts +++ b/src/creation/pruning/normalizeRawESLintRuleSeverity.ts @@ -1,6 +1,6 @@ -import { ESLintRuleSeverity, RawESLintRuleSeverity } from "../types"; +import { ESLintRuleSeverity, RawESLintRuleSeverity } from "../../rules/types"; -export const convertRawESLintRuleSeverity = ( +export const normalizeRawESLintRuleSeverity = ( rawSeverity: RawESLintRuleSeverity, ): ESLintRuleSeverity => { switch (rawSeverity) { diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.test.ts b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts index f859be0f3..37f2ae750 100644 --- a/src/creation/pruning/removeExtendsDuplicatedRules.test.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.test.ts @@ -1,61 +1,53 @@ -import { - ESLintConfiguration, - ESLintConfigurationRuleValue, -} from "../../input/findESLintConfiguration"; -import { ESLintRuleOptions } from "../../rules/types"; +import { ESLintRuleOptions, ESLintRuleOptionsWithArguments } from "../../rules/types"; import { removeExtendsDuplicatedRules } from "./removeExtendsDuplicatedRules"; const prepareTestRule = ( ruleOptions: Partial, - extensionConfiguration: ESLintConfigurationRuleValue, + extensionConfiguration: Partial = {}, ) => { const ruleName = "rule-a"; - const allRules = new Map([ - [ - ruleName, - { - ruleArguments: [], + const createSingleRuleMap = (overrides: Partial) => { + return new Map([ + [ ruleName, - ruleSeverity: "off", - ...ruleOptions, - }, - ], - ]); - const extensions: Partial[] = [ - { - rules: { - [ruleName]: extensionConfiguration, - }, - }, - ]; + { + ruleArguments: [], + ruleName, + ruleSeverity: "off", + ...overrides, + }, + ], + ]); + }; + const allRules = createSingleRuleMap(ruleOptions); + const extensions = createSingleRuleMap(extensionConfiguration); return { ruleName, allRules, extensions }; }; describe("removeExtendsDuplicatedRules", () => { - it("keeps a rule when there are no rules in the extension", () => { + it("keeps a rule when it doesn't match an extended rule", () => { // Arrange - const { allRules } = prepareTestRule( - { - ruleName: "mismatched", - }, - 2, - ); + const { allRules } = prepareTestRule({ + ruleName: "mismatched", + }); // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, [{}]); + const { differentRules } = removeExtendsDuplicatedRules(allRules, new Map()); // Assert expect(differentRules.size).toBe(1); }); - it("keeps a rule when it doesn't match any existing rule", () => { + it("keeps a rule when its severity doesn't match its extended rule", () => { // Arrange const { allRules, extensions } = prepareTestRule( { - ruleName: "mismatched", + ruleSeverity: "warn", + }, + { + ruleSeverity: "error", }, - 2, ); // Act @@ -65,63 +57,36 @@ describe("removeExtendsDuplicatedRules", () => { expect(differentRules.size).toBe(1); }); - it("removes a rule when it matches an existing rule as numbers", () => { + it("keeps a rule when its arguments don't match its extended arguments", () => { // Arrange const { allRules, extensions } = prepareTestRule( { ruleSeverity: "warn", }, - 1, - ); - - // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); - - // Assert - expect(differentRules.size).toBe(0); - }); - - it("removes a rule when it has no arguments and matches an extended rule with an empty arguments array", () => { - // Arrange - const { allRules, extensions } = prepareTestRule( { - ruleArguments: undefined, ruleSeverity: "error", }, - ["error"], ); // Act const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert - expect(differentRules.size).toBe(0); + expect(differentRules.size).toBe(1); }); - it("removes a rule when it has an empty arguments array and matches an extended rule with no arguments", () => { + it("keeps a rule when its arguments don't match its extended arguments", () => { // Arrange + const ruleArguments = [{ value: true }]; const { allRules, extensions } = prepareTestRule( { - ruleArguments: [], - ruleSeverity: "error", + ruleArguments, + ruleSeverity: "warn", }, - ["error"], - ); - - // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); - - // Assert - expect(differentRules.size).toBe(0); - }); - - it("keeps a rule when it conflicts with an existing rule as numbers", () => { - // Arrange - const { allRules, extensions } = prepareTestRule( { - ruleSeverity: "warn", + ruleArguments, + ruleSeverity: "error", }, - 2, ); // Act @@ -131,29 +96,17 @@ describe("removeExtendsDuplicatedRules", () => { expect(differentRules.size).toBe(1); }); - it("removes a rule when it matches an existing rule as strings", () => { + it("keeps a rule when its arguments don't exist and the extended rule has arguments", () => { // Arrange const { allRules, extensions } = prepareTestRule( { + ruleArguments: undefined, ruleSeverity: "warn", }, - "warn", - ); - - // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); - - // Assert - expect(differentRules.size).toBe(0); - }); - - it("keeps a rule when it conflicts with an existing rule as strings", () => { - // Arrange - const { allRules, extensions } = prepareTestRule( { + ruleArguments: [{ value: true }], ruleSeverity: "warn", }, - "error", ); // Act @@ -163,37 +116,185 @@ describe("removeExtendsDuplicatedRules", () => { expect(differentRules.size).toBe(1); }); - it("removes a rule when it matches an existing rule as objects", () => { + it("removes a rule when it matches its extended rule", () => { // Arrange const { allRules, extensions } = prepareTestRule( { - ruleArguments: ["some-argument"], ruleSeverity: "warn", }, - ["warn", "some-argument"], - ); - - // Act - const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); - - // Assert - expect(differentRules.size).toBe(0); - }); - - it("keeps a rule when it conflicts with an existing rule as objects", () => { - // Arrange - const { allRules, extensions } = prepareTestRule( { - ruleArguments: ["some-argument-one"], ruleSeverity: "warn", }, - ["warn", "some-argument-modified"], ); // Act const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); // Assert - expect(differentRules.size).toBe(1); + expect(differentRules.size).toBe(0); }); + + // it("keeps a rule when there are no rules in the extension", () => { + // // Arrange + // const { allRules } = prepareTestRule( + // { + // ruleName: "mismatched", + // }, + // 2, + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, [{}]); + + // // Assert + // expect(differentRules.size).toBe(1); + // }); + + // it("keeps a rule when it doesn't match any existing rule", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleName: "mismatched", + // }, + // 2, + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(1); + // }); + + // it("removes a rule when it matches an existing rule as numbers", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleSeverity: "warn", + // }, + // 1, + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(0); + // }); + + // it("removes a rule when it has no arguments and matches an extended rule with an empty arguments array", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleArguments: undefined, + // ruleSeverity: "error", + // }, + // ["error"], + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(0); + // }); + + // it("removes a rule when it has an empty arguments array and matches an extended rule with no arguments", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleArguments: [], + // ruleSeverity: "error", + // }, + // ["error"], + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(0); + // }); + + // it("keeps a rule when it conflicts with an existing rule as numbers", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleSeverity: "warn", + // }, + // 2, + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(1); + // }); + + // it("removes a rule when it matches an existing rule as strings", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleSeverity: "warn", + // }, + // "warn", + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(0); + // }); + + // it("keeps a rule when it conflicts with an existing rule as strings", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleSeverity: "warn", + // }, + // "error", + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(1); + // }); + + // it("removes a rule when it matches an existing rule as objects", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleArguments: ["some-argument"], + // ruleSeverity: "warn", + // }, + // ["warn", "some-argument"], + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(0); + // }); + + // it("keeps a rule when it conflicts with an existing rule as objects", () => { + // // Arrange + // const { allRules, extensions } = prepareTestRule( + // { + // ruleArguments: ["some-argument-one"], + // ruleSeverity: "warn", + // }, + // ["warn", "some-argument-modified"], + // ); + + // // Act + // const { differentRules } = removeExtendsDuplicatedRules(allRules, extensions); + + // // Assert + // expect(differentRules.size).toBe(1); + // }); }); diff --git a/src/creation/pruning/removeExtendsDuplicatedRules.ts b/src/creation/pruning/removeExtendsDuplicatedRules.ts index 3ac4db5f6..9e7618f74 100644 --- a/src/creation/pruning/removeExtendsDuplicatedRules.ts +++ b/src/creation/pruning/removeExtendsDuplicatedRules.ts @@ -1,23 +1,17 @@ import { isDeepStrictEqual } from "util"; -import { - ESLintConfiguration, - ESLintConfigurationRuleValue, -} from "../../input/findESLintConfiguration"; -import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; import { ESLintRuleOptions, ESLintRuleOptionsWithArguments } from "../../rules/types"; /** - * Finds the ESLint rules that aren't configured the same as their last preset + * Finds only the ESLint rules configured differently than their (extended) configurations. */ export const removeExtendsDuplicatedRules = ( - allRules: Map, - extensions: Partial[], + userRules: Map, + extensionRules: Map, ) => { const differentRules = new Map(); - const extensionRules = mergeExtensions(extensions); - for (const [ruleName, value] of allRules) { + for (const [ruleName, value] of userRules) { if (!ruleValuesAreTheSame(value, extensionRules.get(ruleName))) { differentRules.set(ruleName, value); } @@ -26,49 +20,6 @@ export const removeExtendsDuplicatedRules = ( return { differentRules, extensionRules }; }; -const mergeExtensions = (extensions: Partial[]) => { - const mergedRules = new Map(); - - for (const extension of extensions) { - if (extension.rules === undefined) { - continue; - } - - for (const ruleName in extension.rules) { - mergedRules.set(ruleName, formatRuleArguments(ruleName, extension.rules[ruleName])); - } - } - - return mergedRules; -}; - -const formatRuleArguments = ( - ruleName: string, - originalValue: ESLintConfigurationRuleValue, -): ESLintRuleOptionsWithArguments => { - if (typeof originalValue === "number") { - return { - ruleArguments: [], - ruleName, - ruleSeverity: convertRawESLintRuleSeverity(originalValue), - }; - } - - if (typeof originalValue === "string") { - return { - ruleArguments: [], - ruleName, - ruleSeverity: originalValue, - }; - } - - return { - ruleArguments: originalValue.slice(1), - ruleName, - ruleSeverity: convertRawESLintRuleSeverity(originalValue[0]), - }; -}; - const ruleValuesAreTheSame = ( configurationValue: ESLintRuleOptions, extensionValue: ESLintRuleOptionsWithArguments | undefined, diff --git a/src/creation/summarization/summarizePackageRules.ts b/src/creation/summarization/summarizePackageRules.ts index 10a024f9a..fd94473cc 100644 --- a/src/creation/summarization/summarizePackageRules.ts +++ b/src/creation/summarization/summarizePackageRules.ts @@ -5,6 +5,7 @@ import { TSLintConfiguration } from "../../input/findTSLintConfiguration"; import { RuleConversionResults } from "../../rules/convertRules"; import { uniqueFromSources } from "../../utils"; import { removeExtendsDuplicatedRules } from "../pruning/removeExtendsDuplicatedRules"; +import { normalizeExtensions } from "../pruning/normalizeExtensions"; import { collectTSLintRulesets } from "./collectTSLintRulesets"; import { addPrettierExtensions } from "./prettier/addPrettierExtensions"; import { retrieveExtendsValues } from "./retrieveExtendsValues"; @@ -49,12 +50,13 @@ export const summarizePackageRules = async ( const { configurationErrors, importedExtensions } = await dependencies.retrieveExtendsValues( uniqueFromSources(extendedESLintRulesets, extendedTSLintRulesets), ); + const extensionRules = normalizeExtensions(importedExtensions); const deduplicated = dependencies.removeExtendsDuplicatedRules( new Map([ ...Array.from(normalizeESLintRules(eslint?.full.rules)), ...Array.from(ruleConversionResults.converted), ]), - importedExtensions, + extensionRules, ); return { From 050fe7c76828d9887aeece650ab607ab065dbffe Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 9 May 2020 17:24:44 -0400 Subject: [PATCH 7/7] Fixed compile complaint --- .../convertRawESLintRuleSeverity.test.ts | 47 ------------------- .../summarization/normalizeESLintRules.ts | 4 +- 2 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 src/creation/pruning/convertRawESLintRuleSeverity.test.ts diff --git a/src/creation/pruning/convertRawESLintRuleSeverity.test.ts b/src/creation/pruning/convertRawESLintRuleSeverity.test.ts deleted file mode 100644 index e820acd17..000000000 --- a/src/creation/pruning/convertRawESLintRuleSeverity.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; - -describe("convertRawESLintRuleSeverity", () => { - it("returns off when the severity is 0", () => { - // Arrange - const rawSeverity = 0; - - // Act - const converted = convertRawESLintRuleSeverity(rawSeverity); - - // Assert - expect(converted).toEqual("off"); - }); - - it("returns warn when the severity is 1", () => { - // Arrange - const rawSeverity = 1; - - // Act - const converted = convertRawESLintRuleSeverity(rawSeverity); - - // Assert - expect(converted).toEqual("warn"); - }); - - it("returns error when the severity is 2", () => { - // Arrange - const rawSeverity = 2; - - // Act - const converted = convertRawESLintRuleSeverity(rawSeverity); - - // Assert - expect(converted).toEqual("error"); - }); - - it("returns the original severity when it's a string", () => { - // Arrange - const rawSeverity = "warn"; - - // Act - const converted = convertRawESLintRuleSeverity(rawSeverity); - - // Assert - expect(converted).toEqual("warn"); - }); -}); diff --git a/src/creation/summarization/normalizeESLintRules.ts b/src/creation/summarization/normalizeESLintRules.ts index 33a56e100..7af8660c6 100644 --- a/src/creation/summarization/normalizeESLintRules.ts +++ b/src/creation/summarization/normalizeESLintRules.ts @@ -1,6 +1,6 @@ import { ESLintConfigurationRules } from "../../input/findESLintConfiguration"; -import { convertRawESLintRuleSeverity } from "../../rules/formats/convertRuleSeverity"; import { ESLintRuleOptions } from "../../rules/types"; +import { normalizeRawESLintRuleSeverity } from "../pruning/normalizeRawESLintRuleSeverity"; /** * Normalizes raw ESLint rule configurations into our standardized output format. @@ -11,7 +11,7 @@ export const normalizeESLintRules = (userRules: ESLintConfigurationRules | undef for (const [ruleName, configuration] of Object.entries(userRules ?? {})) { const [rawRuleSeverity, ruleArguments] = configuration instanceof Array ? configuration : [configuration, {}]; - const ruleSeverity = convertRawESLintRuleSeverity(rawRuleSeverity); + const ruleSeverity = normalizeRawESLintRuleSeverity(rawRuleSeverity); output.set(ruleName, { ruleArguments, ruleName, ruleSeverity }); }