From 58190307bc11ba5ad44850d3ffa25463ffb77c6d Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Thu, 13 Nov 2025 23:08:48 -0700 Subject: [PATCH 1/7] Add test for an example config which has problematic behavior here. --- .../eslint-overrides.spec.ts.snap | 231 ++++++++++++++++++ integration_test/eslint-overrides.spec.ts | 5 + .../projects/eslint-overrides.config.ts | 37 +++ 3 files changed, 273 insertions(+) create mode 100644 integration_test/__snapshots__/eslint-overrides.spec.ts.snap create mode 100644 integration_test/eslint-overrides.spec.ts create mode 100644 integration_test/projects/eslint-overrides.config.ts diff --git a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap new file mode 100644 index 00000000..8163e3ad --- /dev/null +++ b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap @@ -0,0 +1,231 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`eslint-overrides > eslint-overrides 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "off", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "overrides": [ + { + "files": [ + "**/*.ts", + "**/*.tsx", + ], + "rules": { + "react/react-in-jsx-scope": "error", + }, + }, + ], + "plugins": [ + "react", + ], + "rules": { + "react/jsx-key": "error", + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "error", + "react/jsx-no-undef": "error", + "react/no-children-prop": "error", + "react/no-danger-with-children": "error", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "error", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-string-refs": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": "error", + }, + }, + "warnings": [ + "unsupported rule: react/display-name", + "unsupported rule: react/jsx-uses-react", + "unsupported rule: react/jsx-uses-vars", + "unsupported rule: react/no-deprecated", + "unsupported rule: react/prop-types", + "unsupported rule, but in development: react/require-render-return", + ], +} +`; + +exports[`eslint-overrides --js-plugins > eslint-overrides--js-plugins 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "off", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "overrides": [ + { + "files": [ + "**/*.ts", + "**/*.tsx", + ], + "rules": { + "react/react-in-jsx-scope": "error", + }, + }, + ], + "plugins": [ + "react", + ], + "rules": { + "react/jsx-key": "error", + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "error", + "react/jsx-no-undef": "error", + "react/no-children-prop": "error", + "react/no-danger-with-children": "error", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "error", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-string-refs": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": "error", + }, + }, + "warnings": [ + "unsupported rule: react/display-name", + "unsupported rule: react/jsx-uses-react", + "unsupported rule: react/jsx-uses-vars", + "unsupported rule: react/no-deprecated", + "unsupported rule: react/prop-types", + "unsupported rule, but in development: react/require-render-return", + ], +} +`; + +exports[`eslint-overrides --type-aware > eslint-overrides--type-aware 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "off", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "overrides": [ + { + "files": [ + "**/*.ts", + "**/*.tsx", + ], + "rules": { + "react/react-in-jsx-scope": "error", + }, + }, + ], + "plugins": [ + "react", + ], + "rules": { + "react/jsx-key": "error", + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "error", + "react/jsx-no-undef": "error", + "react/no-children-prop": "error", + "react/no-danger-with-children": "error", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "error", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-string-refs": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": "error", + }, + }, + "warnings": [ + "unsupported rule: react/display-name", + "unsupported rule: react/jsx-uses-react", + "unsupported rule: react/jsx-uses-vars", + "unsupported rule: react/no-deprecated", + "unsupported rule: react/prop-types", + "unsupported rule, but in development: react/require-render-return", + ], +} +`; + +exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "error", + "perf": "error", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "overrides": [ + { + "files": [ + "**/*.ts", + "**/*.tsx", + ], + "rules": { + "react/jsx-key": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-undef": "error", + "react/no-children-prop": "error", + "react/no-danger-with-children": "error", + "react/no-direct-mutation-state": "error", + "react/no-find-dom-node": "error", + "react/no-is-mounted": "error", + "react/no-render-return-value": "error", + "react/no-string-refs": "error", + }, + }, + { + "files": [ + "**/*.ts", + "**/*.tsx", + ], + "rules": { + "react/react-in-jsx-scope": "off", + }, + }, + ], + "plugins": [ + "react", + ], + "rules": { + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-target-blank": "error", + "react/no-unescaped-entities": "error", + "react/no-unknown-property": "error", + "react/react-in-jsx-scope": "error", + }, + }, + "warnings": [ + "unsupported rule: react/display-name", + "unsupported rule: react/jsx-uses-react", + "unsupported rule: react/jsx-uses-vars", + "unsupported rule: react/no-deprecated", + "unsupported rule: react/prop-types", + "unsupported rule, but in development: react/require-render-return", + ], +} +`; diff --git a/integration_test/eslint-overrides.spec.ts b/integration_test/eslint-overrides.spec.ts new file mode 100644 index 00000000..f39dcd7b --- /dev/null +++ b/integration_test/eslint-overrides.spec.ts @@ -0,0 +1,5 @@ +import eslint_overrides_test from './projects/eslint-overrides.config.js'; +import { testProject } from './utils.js'; + +// @ts-expect-error +testProject('eslint-overrides', eslint_overrides_test); diff --git a/integration_test/projects/eslint-overrides.config.ts b/integration_test/projects/eslint-overrides.config.ts new file mode 100644 index 00000000..ddb9e515 --- /dev/null +++ b/integration_test/projects/eslint-overrides.config.ts @@ -0,0 +1,37 @@ +import { globalIgnores } from 'eslint/config'; +import react from 'eslint-plugin-react'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config([ + globalIgnores(['node_modules/**/*']), + react.configs.flat.recommended, + react.configs.flat['jsx-runtime'], + { + languageOptions: { + parser: tseslint.parser, + sourceType: 'module', + }, + + settings: { + react: { + version: 'detect', + }, + }, + + rules: { + 'react/jsx-filename-extension': 'off', + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + + extends: [ + react.configs.flat.recommended, + react.configs.flat['jsx-runtime'], + ], + + rules: { + 'react/prop-types': 'off', + }, + }, +]); From 5bee41dff8a37612ddaa5f7fbf0f72afd200f554 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Thu, 13 Nov 2025 23:24:30 -0700 Subject: [PATCH 2/7] Minimal repro case. --- .../eslint-overrides.spec.ts.snap | 109 ++---------------- .../projects/eslint-overrides.config.ts | 24 ++-- 2 files changed, 23 insertions(+), 110 deletions(-) diff --git a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap index 8163e3ad..dd1403ee 100644 --- a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap +++ b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap @@ -27,31 +27,9 @@ exports[`eslint-overrides > eslint-overrides 1`] = ` "plugins": [ "react", ], - "rules": { - "react/jsx-key": "error", - "react/jsx-no-comment-textnodes": "error", - "react/jsx-no-duplicate-props": "error", - "react/jsx-no-target-blank": "error", - "react/jsx-no-undef": "error", - "react/no-children-prop": "error", - "react/no-danger-with-children": "error", - "react/no-direct-mutation-state": "error", - "react/no-find-dom-node": "error", - "react/no-is-mounted": "error", - "react/no-render-return-value": "error", - "react/no-string-refs": "error", - "react/no-unescaped-entities": "error", - "react/no-unknown-property": "error", - }, + "rules": {}, }, - "warnings": [ - "unsupported rule: react/display-name", - "unsupported rule: react/jsx-uses-react", - "unsupported rule: react/jsx-uses-vars", - "unsupported rule: react/no-deprecated", - "unsupported rule: react/prop-types", - "unsupported rule, but in development: react/require-render-return", - ], + "warnings": [], } `; @@ -82,31 +60,9 @@ exports[`eslint-overrides --js-plugins > eslint-overrides--js-plugins 1`] = ` "plugins": [ "react", ], - "rules": { - "react/jsx-key": "error", - "react/jsx-no-comment-textnodes": "error", - "react/jsx-no-duplicate-props": "error", - "react/jsx-no-target-blank": "error", - "react/jsx-no-undef": "error", - "react/no-children-prop": "error", - "react/no-danger-with-children": "error", - "react/no-direct-mutation-state": "error", - "react/no-find-dom-node": "error", - "react/no-is-mounted": "error", - "react/no-render-return-value": "error", - "react/no-string-refs": "error", - "react/no-unescaped-entities": "error", - "react/no-unknown-property": "error", - }, + "rules": {}, }, - "warnings": [ - "unsupported rule: react/display-name", - "unsupported rule: react/jsx-uses-react", - "unsupported rule: react/jsx-uses-vars", - "unsupported rule: react/no-deprecated", - "unsupported rule: react/prop-types", - "unsupported rule, but in development: react/require-render-return", - ], + "warnings": [], } `; @@ -137,31 +93,9 @@ exports[`eslint-overrides --type-aware > eslint-overrides--type-aware 1`] = ` "plugins": [ "react", ], - "rules": { - "react/jsx-key": "error", - "react/jsx-no-comment-textnodes": "error", - "react/jsx-no-duplicate-props": "error", - "react/jsx-no-target-blank": "error", - "react/jsx-no-undef": "error", - "react/no-children-prop": "error", - "react/no-danger-with-children": "error", - "react/no-direct-mutation-state": "error", - "react/no-find-dom-node": "error", - "react/no-is-mounted": "error", - "react/no-render-return-value": "error", - "react/no-string-refs": "error", - "react/no-unescaped-entities": "error", - "react/no-unknown-property": "error", - }, + "rules": {}, }, - "warnings": [ - "unsupported rule: react/display-name", - "unsupported rule: react/jsx-uses-react", - "unsupported rule: react/jsx-uses-vars", - "unsupported rule: react/no-deprecated", - "unsupported rule: react/prop-types", - "unsupported rule, but in development: react/require-render-return", - ], + "warnings": [], } `; @@ -180,24 +114,6 @@ exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` "node_modules/**/*", ], "overrides": [ - { - "files": [ - "**/*.ts", - "**/*.tsx", - ], - "rules": { - "react/jsx-key": "error", - "react/jsx-no-duplicate-props": "error", - "react/jsx-no-undef": "error", - "react/no-children-prop": "error", - "react/no-danger-with-children": "error", - "react/no-direct-mutation-state": "error", - "react/no-find-dom-node": "error", - "react/no-is-mounted": "error", - "react/no-render-return-value": "error", - "react/no-string-refs": "error", - }, - }, { "files": [ "**/*.ts", @@ -212,20 +128,9 @@ exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` "react", ], "rules": { - "react/jsx-no-comment-textnodes": "error", - "react/jsx-no-target-blank": "error", - "react/no-unescaped-entities": "error", - "react/no-unknown-property": "error", "react/react-in-jsx-scope": "error", }, }, - "warnings": [ - "unsupported rule: react/display-name", - "unsupported rule: react/jsx-uses-react", - "unsupported rule: react/jsx-uses-vars", - "unsupported rule: react/no-deprecated", - "unsupported rule: react/prop-types", - "unsupported rule, but in development: react/require-render-return", - ], + "warnings": [], } `; diff --git a/integration_test/projects/eslint-overrides.config.ts b/integration_test/projects/eslint-overrides.config.ts index ddb9e515..ae1239b4 100644 --- a/integration_test/projects/eslint-overrides.config.ts +++ b/integration_test/projects/eslint-overrides.config.ts @@ -1,11 +1,22 @@ import { globalIgnores } from 'eslint/config'; -import react from 'eslint-plugin-react'; -import tseslint from 'typescript-eslint'; +import tseslint, { type ConfigWithExtends } from 'typescript-eslint'; + +const config1: ConfigWithExtends = { + rules: { + 'react/react-in-jsx-scope': 'error', + }, +}; + +const config2: ConfigWithExtends = { + rules: { + 'react/react-in-jsx-scope': 'off', + }, +}; export default tseslint.config([ globalIgnores(['node_modules/**/*']), - react.configs.flat.recommended, - react.configs.flat['jsx-runtime'], + config1, + config2, { languageOptions: { parser: tseslint.parser, @@ -25,10 +36,7 @@ export default tseslint.config([ { files: ['**/*.ts', '**/*.tsx'], - extends: [ - react.configs.flat.recommended, - react.configs.flat['jsx-runtime'], - ], + extends: [config1, config2], rules: { 'react/prop-types': 'off', From d70516735757895a140dc14ca0800ffdbcd64baa Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 14 Nov 2025 00:03:02 -0700 Subject: [PATCH 3/7] Fix the plugin_rules logic for collapsing the overrides into each other. --- .../eslint-overrides.spec.ts.snap | 102 ------------------ .../projects/eslint-overrides.config.ts | 1 + src/plugin_rules.spec.ts | 43 ++++++++ src/plugins_rules.ts | 68 +++++++++++- 4 files changed, 111 insertions(+), 103 deletions(-) diff --git a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap index dd1403ee..98e6de7c 100644 --- a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap +++ b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap @@ -32,105 +32,3 @@ exports[`eslint-overrides > eslint-overrides 1`] = ` "warnings": [], } `; - -exports[`eslint-overrides --js-plugins > eslint-overrides--js-plugins 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "off", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "overrides": [ - { - "files": [ - "**/*.ts", - "**/*.tsx", - ], - "rules": { - "react/react-in-jsx-scope": "error", - }, - }, - ], - "plugins": [ - "react", - ], - "rules": {}, - }, - "warnings": [], -} -`; - -exports[`eslint-overrides --type-aware > eslint-overrides--type-aware 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "off", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "overrides": [ - { - "files": [ - "**/*.ts", - "**/*.tsx", - ], - "rules": { - "react/react-in-jsx-scope": "error", - }, - }, - ], - "plugins": [ - "react", - ], - "rules": {}, - }, - "warnings": [], -} -`; - -exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "error", - "perf": "error", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "overrides": [ - { - "files": [ - "**/*.ts", - "**/*.tsx", - ], - "rules": { - "react/react-in-jsx-scope": "off", - }, - }, - ], - "plugins": [ - "react", - ], - "rules": { - "react/react-in-jsx-scope": "error", - }, - }, - "warnings": [], -} -`; diff --git a/integration_test/projects/eslint-overrides.config.ts b/integration_test/projects/eslint-overrides.config.ts index ae1239b4..52a8809d 100644 --- a/integration_test/projects/eslint-overrides.config.ts +++ b/integration_test/projects/eslint-overrides.config.ts @@ -36,6 +36,7 @@ export default tseslint.config([ { files: ['**/*.ts', '**/*.tsx'], + // The second config should override the first if they have the same rule with the same settings. extends: [config1, config2], rules: { diff --git a/src/plugin_rules.spec.ts b/src/plugin_rules.spec.ts index 9257ca32..a32810b2 100644 --- a/src/plugin_rules.spec.ts +++ b/src/plugin_rules.spec.ts @@ -147,6 +147,49 @@ describe('rules and plugins', () => { }); }); + test('cleanUpUselessOverridesRules with multiple overrides for same files (last-wins)', () => { + const config: OxlintConfig = { + rules: { + 'react/react-in-jsx-scope': 'off', + }, + overrides: [ + { + files: ['**/*.ts', '**/*.tsx'], + rules: { + 'react/foobar': 'error', + 'react/react-in-jsx-scope': 'error', + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + rules: { + 'react/react-in-jsx-scope': 'off', + }, + }, + ], + }; + + cleanUpUselessOverridesRules(config); + + // The final rule wins over the first, so react-in-jsx-scope should end up as "off". + expect(config).toStrictEqual({ + rules: { + 'react/react-in-jsx-scope': 'off', + }, + overrides: [ + { + files: ['**/*.ts', '**/*.tsx'], + rules: { + 'react/foobar': 'error', + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + }, + ], + }); + }); + test('cleanUpRulesWhichAreCoveredByCategory', () => { const config: OxlintConfig = { categories: { diff --git a/src/plugins_rules.ts b/src/plugins_rules.ts index 2e3dad94..08eb5748 100644 --- a/src/plugins_rules.ts +++ b/src/plugins_rules.ts @@ -179,13 +179,79 @@ export const cleanUpUselessOverridesPlugins = (config: OxlintConfig): void => { } } }; + export const cleanUpUselessOverridesRules = (config: OxlintConfig): void => { if (config.rules === undefined || config.overrides === undefined) { return; } + // Build a map of files pattern -> {firstOverrideIndex, finalMergedRules} + const filesPatternMap = new Map< + string, + { + firstIndex: number; + finalRules: Record; + indicesToRemove: number[]; + } + >(); + + // First pass: merge all overrides with same files pattern + for (let i = 0; i < config.overrides.length; i++) { + const override = config.overrides[i]; + if (override.files === undefined) { + continue; + } + + const filesKey = JSON.stringify(override.files); + let entry = filesPatternMap.get(filesKey); + + if (!entry) { + entry = { + firstIndex: i, + finalRules: {}, + indicesToRemove: [], + }; + filesPatternMap.set(filesKey, entry); + } else { + // Mark this duplicate for removal + entry.indicesToRemove.push(i); + } + + // Merge rules with last-wins semantics + if (override.rules) { + Object.assign(entry.finalRules, override.rules); + } + } + + // Second pass: update first occurrence with merged rules and mark duplicates for deletion + for (const [_filesKey, entry] of filesPatternMap.entries()) { + const firstOverride = config.overrides[entry.firstIndex]; + + // Update the first override with the final merged rules + firstOverride.rules = entry.finalRules; + + // Remove rules that match root config + if (firstOverride.rules) { + for (const [rule, settings] of Object.entries(firstOverride.rules)) { + if (config.rules[rule] === settings) { + delete firstOverride.rules[rule]; + } + } + + if (Object.keys(firstOverride.rules).length === 0) { + delete firstOverride.rules; + } + } + + // Mark duplicate overrides for removal by clearing their rules + for (const indexToRemove of entry.indicesToRemove) { + delete config.overrides[indexToRemove].rules; + } + } + + // Handle overrides that don't have files (just clean up rules matching root) for (const override of config.overrides) { - if (override.rules === undefined) { + if (override.files !== undefined || override.rules === undefined) { continue; } From da729110ccb6ae6d65bdf185761e03643d37a488 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 14 Nov 2025 00:03:10 -0700 Subject: [PATCH 4/7] Update the other snaps. --- .../eslint-overrides.spec.ts.snap | 73 ++- .../__snapshots__/nuxt-auth.spec.ts.snap | 52 +- .../__snapshots__/pupeeteer.spec.ts.snap | 598 ++++++------------ .../__snapshots__/typescript.spec.ts.snap | 113 +--- 4 files changed, 299 insertions(+), 537 deletions(-) diff --git a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap index 98e6de7c..54b65e09 100644 --- a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap +++ b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap @@ -13,6 +13,73 @@ exports[`eslint-overrides > eslint-overrides 1`] = ` "ignorePatterns": [ "node_modules/**/*", ], + "plugins": [ + "react", + ], + "rules": {}, + }, + "warnings": [], +} +`; + +exports[`eslint-overrides --js-plugins > eslint-overrides--js-plugins 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "off", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "plugins": [ + "react", + ], + "rules": {}, + }, + "warnings": [], +} +`; + +exports[`eslint-overrides --type-aware > eslint-overrides--type-aware 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "off", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], + "plugins": [ + "react", + ], + "rules": {}, + }, + "warnings": [], +} +`; + +exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` +{ + "config": { + "$schema": "./node_modules/oxlint/configuration_schema.json", + "categories": { + "correctness": "error", + "perf": "error", + }, + "env": { + "builtin": true, + }, + "ignorePatterns": [ + "node_modules/**/*", + ], "overrides": [ { "files": [ @@ -20,14 +87,16 @@ exports[`eslint-overrides > eslint-overrides 1`] = ` "**/*.tsx", ], "rules": { - "react/react-in-jsx-scope": "error", + "react/react-in-jsx-scope": "off", }, }, ], "plugins": [ "react", ], - "rules": {}, + "rules": { + "react/react-in-jsx-scope": "error", + }, }, "warnings": [], } diff --git a/integration_test/__snapshots__/nuxt-auth.spec.ts.snap b/integration_test/__snapshots__/nuxt-auth.spec.ts.snap index b1132a62..99030c6f 100644 --- a/integration_test/__snapshots__/nuxt-auth.spec.ts.snap +++ b/integration_test/__snapshots__/nuxt-auth.spec.ts.snap @@ -133,9 +133,6 @@ exports[`nuxt-auth > nuxt-auth 1`] = ` "**/*.?([cm])tsx", "**/*.vue", ], - "plugins": [ - "typescript", - ], "rules": { "@typescript-eslint/ban-ts-comment": [ "error", @@ -211,6 +208,16 @@ exports[`nuxt-auth > nuxt-auth 1`] = ` "no-with": "off", }, }, + { + "files": [ + "**/*.?([cm])ts", + "**/*.?([cm])tsx", + "**/*.vue", + ], + "plugins": [ + "typescript", + ], + }, { "files": [ "**/__tests__/**/*.?([cm])[jt]s?(x)", @@ -1004,9 +1011,6 @@ exports[`nuxt-auth --js-plugins > nuxt-auth--js-plugins 1`] = ` "**/*.?([cm])tsx", "**/*.vue", ], - "plugins": [ - "typescript", - ], "rules": { "@typescript-eslint/ban-ts-comment": [ "error", @@ -1082,6 +1086,16 @@ exports[`nuxt-auth --js-plugins > nuxt-auth--js-plugins 1`] = ` "no-with": "off", }, }, + { + "files": [ + "**/*.?([cm])ts", + "**/*.?([cm])tsx", + "**/*.vue", + ], + "plugins": [ + "typescript", + ], + }, { "files": [ "**/__tests__/**/*.?([cm])[jt]s?(x)", @@ -2260,9 +2274,6 @@ exports[`nuxt-auth --type-aware > nuxt-auth--type-aware 1`] = ` "**/*.?([cm])tsx", "**/*.vue", ], - "plugins": [ - "typescript", - ], "rules": { "@typescript-eslint/ban-ts-comment": [ "error", @@ -2338,6 +2349,16 @@ exports[`nuxt-auth --type-aware > nuxt-auth--type-aware 1`] = ` "no-with": "off", }, }, + { + "files": [ + "**/*.?([cm])ts", + "**/*.?([cm])tsx", + "**/*.vue", + ], + "plugins": [ + "typescript", + ], + }, { "files": [ "**/__tests__/**/*.?([cm])[jt]s?(x)", @@ -3123,9 +3144,6 @@ exports[`nuxt-auth merge > nuxt-auth--merge 1`] = ` "**/*.?([cm])tsx", "**/*.vue", ], - "plugins": [ - "typescript", - ], "rules": { "@typescript-eslint/ban-ts-comment": [ "error", @@ -3202,6 +3220,16 @@ exports[`nuxt-auth merge > nuxt-auth--merge 1`] = ` "no-with": "off", }, }, + { + "files": [ + "**/*.?([cm])ts", + "**/*.?([cm])tsx", + "**/*.vue", + ], + "plugins": [ + "typescript", + ], + }, { "files": [ "**/__tests__/**/*.?([cm])[jt]s?(x)", diff --git a/integration_test/__snapshots__/pupeeteer.spec.ts.snap b/integration_test/__snapshots__/pupeeteer.spec.ts.snap index a30713f1..94650845 100644 --- a/integration_test/__snapshots__/pupeeteer.spec.ts.snap +++ b/integration_test/__snapshots__/pupeeteer.spec.ts.snap @@ -60,61 +60,35 @@ exports[`puppeteer > puppeteer 1`] = ` "**/*.ts", ], "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "plugins": [ - "typescript", - ], - "rules": { + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": [ + "error", + { + "default": "array-simple", + }, + ], "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-tslint-comment": "error", + "@typescript-eslint/consistent-generic-constructors": "error", + "@typescript-eslint/consistent-indexed-object-style": "error", + "@typescript-eslint/consistent-type-definitions": [ + "error", + "interface", + ], + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/no-empty-object-type": "error", - "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-this-alias": "error", "@typescript-eslint/no-unnecessary-type-constraint": "error", @@ -122,22 +96,17 @@ exports[`puppeteer > puppeteer 1`] = ` "@typescript-eslint/no-unsafe-function-type": "error", "@typescript-eslint/no-wrapper-object-types": "error", "@typescript-eslint/prefer-as-const": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/prefer-ts-expect-error": "error", "@typescript-eslint/triple-slash-reference": "error", "no-array-constructor": "error", - "no-unused-expressions": "error", - "no-unused-vars": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { "no-class-assign": "off", "no-const-assign": "off", "no-dupe-class-members": "off", "no-dupe-keys": "off", + "no-empty-function": "off", "no-func-assign": "off", "no-import-assign": "off", "no-new-native-nonconstructor": "off", @@ -146,6 +115,14 @@ exports[`puppeteer > puppeteer 1`] = ` "no-setter-return": "off", "no-this-before-super": "off", "no-unsafe-negation": "off", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + }, + ], "no-with": "off", "prefer-rest-params": "error", "prefer-spread": "error", @@ -158,19 +135,6 @@ exports[`puppeteer > puppeteer 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-tslint-comment": "error", - "@typescript-eslint/consistent-generic-constructors": "error", - "@typescript-eslint/consistent-indexed-object-style": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/no-confusing-non-null-assertion": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "no-empty-function": "error", - }, }, { "files": [ @@ -179,35 +143,14 @@ exports[`puppeteer > puppeteer 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/array-type": [ - "error", - { - "default": "array-simple", - }, - ], - "@typescript-eslint/consistent-type-definitions": [ - "error", - "interface", - ], - "@typescript-eslint/consistent-type-imports": "error", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-import-type-side-effects": "error", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unsafe-function-type": "error", - "@typescript-eslint/no-wrapper-object-types": "error", - "@typescript-eslint/prefer-ts-expect-error": "error", - "no-empty-function": "off", - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", - }, - ], - }, + }, + { + "files": [ + "**/*.ts", + ], + "plugins": [ + "typescript", + ], }, { "files": [ @@ -413,61 +356,36 @@ exports[`puppeteer --js-plugins > puppeteer--js-plugins 1`] = ` "**/*.ts", ], "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "plugins": [ - "typescript", - ], - "rules": { + "@puppeteer/use-using": "error", + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": [ + "error", + { + "default": "array-simple", + }, + ], "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-tslint-comment": "error", + "@typescript-eslint/consistent-generic-constructors": "error", + "@typescript-eslint/consistent-indexed-object-style": "error", + "@typescript-eslint/consistent-type-definitions": [ + "error", + "interface", + ], + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/no-empty-object-type": "error", - "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-this-alias": "error", "@typescript-eslint/no-unnecessary-type-constraint": "error", @@ -475,22 +393,17 @@ exports[`puppeteer --js-plugins > puppeteer--js-plugins 1`] = ` "@typescript-eslint/no-unsafe-function-type": "error", "@typescript-eslint/no-wrapper-object-types": "error", "@typescript-eslint/prefer-as-const": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/prefer-ts-expect-error": "error", "@typescript-eslint/triple-slash-reference": "error", "no-array-constructor": "error", - "no-unused-expressions": "error", - "no-unused-vars": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { "no-class-assign": "off", "no-const-assign": "off", "no-dupe-class-members": "off", "no-dupe-keys": "off", + "no-empty-function": "off", "no-func-assign": "off", "no-import-assign": "off", "no-new-native-nonconstructor": "off", @@ -499,6 +412,14 @@ exports[`puppeteer --js-plugins > puppeteer--js-plugins 1`] = ` "no-setter-return": "off", "no-this-before-super": "off", "no-unsafe-negation": "off", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + }, + ], "no-with": "off", "prefer-rest-params": "error", "prefer-spread": "error", @@ -511,19 +432,14 @@ exports[`puppeteer --js-plugins > puppeteer--js-plugins 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-tslint-comment": "error", - "@typescript-eslint/consistent-generic-constructors": "error", - "@typescript-eslint/consistent-indexed-object-style": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/no-confusing-non-null-assertion": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "no-empty-function": "error", - }, + }, + { + "files": [ + "**/*.ts", + ], + "plugins": [ + "typescript", + ], }, { "files": [ @@ -535,36 +451,6 @@ exports[`puppeteer --js-plugins > puppeteer--js-plugins 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@puppeteer/use-using": "error", - "@typescript-eslint/array-type": [ - "error", - { - "default": "array-simple", - }, - ], - "@typescript-eslint/consistent-type-definitions": [ - "error", - "interface", - ], - "@typescript-eslint/consistent-type-imports": "error", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-import-type-side-effects": "error", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unsafe-function-type": "error", - "@typescript-eslint/no-wrapper-object-types": "error", - "@typescript-eslint/prefer-ts-expect-error": "error", - "no-empty-function": "off", - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", - }, - ], - }, }, { "files": [ @@ -768,93 +654,74 @@ exports[`puppeteer --type-aware > puppeteer--type-aware 1`] = ` "packages/ng-schematics/src/**/files/", "examples/puppeteer-in-browser/out/**/*", "examples/puppeteer-in-browser/node_modules/**/*", - "examples/puppeteer-in-extension/out/**/*", - "examples/puppeteer-in-extension/node_modules/**/*", - ], - "overrides": [ - { - "files": [ - "**/*.ts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, + "examples/puppeteer-in-extension/out/**/*", + "examples/puppeteer-in-extension/node_modules/**/*", + ], + "overrides": [ { "files": [ "**/*.ts", ], - "plugins": [ - "typescript", - ], "rules": { + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": [ + "error", + { + "default": "array-simple", + }, + ], "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-tslint-comment": "error", + "@typescript-eslint/consistent-generic-constructors": "error", + "@typescript-eslint/consistent-indexed-object-style": "error", + "@typescript-eslint/consistent-type-definitions": [ + "error", + "interface", + ], + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/no-empty-object-type": "error", - "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-floating-promises": [ + "error", + { + "ignoreIIFE": true, + "ignoreVoid": true, + }, + ], + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-this-alias": "error", + "@typescript-eslint/no-unnecessary-template-expression": "error", "@typescript-eslint/no-unnecessary-type-constraint": "error", "@typescript-eslint/no-unsafe-declaration-merging": "error", "@typescript-eslint/no-unsafe-function-type": "error", "@typescript-eslint/no-wrapper-object-types": "error", "@typescript-eslint/prefer-as-const": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/prefer-ts-expect-error": "error", + "@typescript-eslint/return-await": [ + "error", + "always", + ], "@typescript-eslint/triple-slash-reference": "error", "no-array-constructor": "error", - "no-unused-expressions": "error", - "no-unused-vars": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { "no-class-assign": "off", "no-const-assign": "off", "no-dupe-class-members": "off", "no-dupe-keys": "off", + "no-empty-function": "off", "no-func-assign": "off", "no-import-assign": "off", "no-new-native-nonconstructor": "off", @@ -863,6 +730,14 @@ exports[`puppeteer --type-aware > puppeteer--type-aware 1`] = ` "no-setter-return": "off", "no-this-before-super": "off", "no-unsafe-negation": "off", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + }, + ], "no-with": "off", "prefer-rest-params": "error", "prefer-spread": "error", @@ -875,19 +750,6 @@ exports[`puppeteer --type-aware > puppeteer--type-aware 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-tslint-comment": "error", - "@typescript-eslint/consistent-generic-constructors": "error", - "@typescript-eslint/consistent-indexed-object-style": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/no-confusing-non-null-assertion": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "no-empty-function": "error", - }, }, { "files": [ @@ -896,47 +758,14 @@ exports[`puppeteer --type-aware > puppeteer--type-aware 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/array-type": [ - "error", - { - "default": "array-simple", - }, - ], - "@typescript-eslint/consistent-type-definitions": [ - "error", - "interface", - ], - "@typescript-eslint/consistent-type-imports": "error", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-floating-promises": [ - "error", - { - "ignoreIIFE": true, - "ignoreVoid": true, - }, - ], - "@typescript-eslint/no-import-type-side-effects": "error", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unnecessary-template-expression": "error", - "@typescript-eslint/no-unsafe-function-type": "error", - "@typescript-eslint/no-wrapper-object-types": "error", - "@typescript-eslint/prefer-ts-expect-error": "error", - "@typescript-eslint/return-await": [ - "error", - "always", - ], - "no-empty-function": "off", - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", - }, - ], - }, + }, + { + "files": [ + "**/*.ts", + ], + "plugins": [ + "typescript", + ], }, { "files": [ @@ -1146,61 +975,35 @@ exports[`puppeteer merge > puppeteer--merge 1`] = ` "**/*.ts", ], "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "plugins": [ - "typescript", - ], - "rules": { + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": [ + "error", + { + "default": "array-simple", + }, + ], "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/ban-tslint-comment": "error", + "@typescript-eslint/consistent-generic-constructors": "error", + "@typescript-eslint/consistent-indexed-object-style": "error", + "@typescript-eslint/consistent-type-definitions": [ + "error", + "interface", + ], + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/no-empty-object-type": "error", - "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-extra-non-null-assertion": "error", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-this-alias": "error", "@typescript-eslint/no-unnecessary-type-constraint": "error", @@ -1208,22 +1011,17 @@ exports[`puppeteer merge > puppeteer--merge 1`] = ` "@typescript-eslint/no-unsafe-function-type": "error", "@typescript-eslint/no-wrapper-object-types": "error", "@typescript-eslint/prefer-as-const": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/prefer-ts-expect-error": "error", "@typescript-eslint/triple-slash-reference": "error", "no-array-constructor": "error", - "no-unused-expressions": "error", - "no-unused-vars": "error", - }, - }, - { - "files": [ - "**/*.ts", - ], - "rules": { "no-class-assign": "off", "no-const-assign": "off", "no-dupe-class-members": "off", "no-dupe-keys": "off", + "no-empty-function": "off", "no-func-assign": "off", "no-import-assign": "off", "no-new-native-nonconstructor": "off", @@ -1232,6 +1030,14 @@ exports[`puppeteer merge > puppeteer--merge 1`] = ` "no-setter-return": "off", "no-this-before-super": "off", "no-unsafe-negation": "off", + "no-unused-expressions": "error", + "no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + }, + ], "no-with": "off", "prefer-rest-params": "error", "prefer-spread": "error", @@ -1244,19 +1050,6 @@ exports[`puppeteer merge > puppeteer--merge 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", - "@typescript-eslint/ban-tslint-comment": "error", - "@typescript-eslint/consistent-generic-constructors": "error", - "@typescript-eslint/consistent-indexed-object-style": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/no-confusing-non-null-assertion": "error", - "@typescript-eslint/no-inferrable-types": "error", - "@typescript-eslint/prefer-for-of": "error", - "@typescript-eslint/prefer-function-type": "error", - "no-empty-function": "error", - }, }, { "files": [ @@ -1265,35 +1058,14 @@ exports[`puppeteer merge > puppeteer--merge 1`] = ` "plugins": [ "typescript", ], - "rules": { - "@typescript-eslint/array-type": [ - "error", - { - "default": "array-simple", - }, - ], - "@typescript-eslint/consistent-type-definitions": [ - "error", - "interface", - ], - "@typescript-eslint/consistent-type-imports": "error", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "error", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-import-type-side-effects": "error", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unsafe-function-type": "error", - "@typescript-eslint/no-wrapper-object-types": "error", - "@typescript-eslint/prefer-ts-expect-error": "error", - "no-empty-function": "off", - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", - }, - ], - }, + }, + { + "files": [ + "**/*.ts", + ], + "plugins": [ + "typescript", + ], }, { "files": [ diff --git a/integration_test/__snapshots__/typescript.spec.ts.snap b/integration_test/__snapshots__/typescript.spec.ts.snap index efa429ac..bed684bd 100644 --- a/integration_test/__snapshots__/typescript.spec.ts.snap +++ b/integration_test/__snapshots__/typescript.spec.ts.snap @@ -50,31 +50,6 @@ exports[`typescript > typescript 1`] = ` "prefer-spread": "error", }, }, - { - "files": [ - "**/*.ts", - "**/*.tsx", - "**/*.mts", - "**/*.cts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, { "files": [ "**/*.mjs", @@ -445,31 +420,6 @@ exports[`typescript --js-plugins > typescript--js-plugins 1`] = ` "prefer-spread": "error", }, }, - { - "files": [ - "**/*.ts", - "**/*.tsx", - "**/*.mts", - "**/*.cts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, { "files": [ "**/*.mjs", @@ -837,31 +787,6 @@ exports[`typescript --type-aware > typescript--type-aware 1`] = ` "prefer-spread": "error", }, }, - { - "files": [ - "**/*.ts", - "**/*.tsx", - "**/*.mts", - "**/*.cts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, { "files": [ "**/*.mjs", @@ -956,12 +881,15 @@ exports[`typescript --type-aware > typescript--type-aware 1`] = ` "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-unsafe-enum-comparison": "off", + "@typescript-eslint/no-unsafe-function-type": "off", "@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-return": "off", "@typescript-eslint/no-unsafe-type-assertion": "off", "@typescript-eslint/no-unsafe-unary-minus": "off", + "@typescript-eslint/no-wrapper-object-types": "off", "@typescript-eslint/non-nullable-type-assertion-style": "off", "@typescript-eslint/only-throw-error": "off", + "@typescript-eslint/prefer-function-type": "off", "@typescript-eslint/prefer-includes": "off", "@typescript-eslint/prefer-promise-reject-errors": "off", "@typescript-eslint/prefer-reduce-type-parameter": "off", @@ -977,16 +905,6 @@ exports[`typescript --type-aware > typescript--type-aware 1`] = ` "@typescript-eslint/switch-exhaustiveness-check": "off", "@typescript-eslint/unbound-method": "off", "@typescript-eslint/use-unknown-in-catch-callback-variable": "off", - }, - }, - { - "files": [ - "src/lib/*.d.ts", - ], - "rules": { - "@typescript-eslint/no-unsafe-function-type": "off", - "@typescript-eslint/no-wrapper-object-types": "off", - "@typescript-eslint/prefer-function-type": "off", "no-restricted-globals": "off", "no-shadow-restricted-names": "off", "no-unused-vars": "off", @@ -1238,31 +1156,6 @@ exports[`typescript merge > typescript--merge 1`] = ` "prefer-spread": "error", }, }, - { - "files": [ - "**/*.ts", - "**/*.tsx", - "**/*.mts", - "**/*.cts", - ], - "rules": { - "no-class-assign": "off", - "no-const-assign": "off", - "no-dupe-class-members": "off", - "no-dupe-keys": "off", - "no-func-assign": "off", - "no-import-assign": "off", - "no-new-native-nonconstructor": "off", - "no-obj-calls": "off", - "no-redeclare": "off", - "no-setter-return": "off", - "no-this-before-super": "off", - "no-unsafe-negation": "off", - "no-with": "off", - "prefer-rest-params": "error", - "prefer-spread": "error", - }, - }, { "files": [ "**/*.mjs", From 250c264d4d9d4805d258dba91f044b52633c7211 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 14 Nov 2025 00:20:27 -0700 Subject: [PATCH 5/7] Remove unnecessary extras. --- .../projects/eslint-overrides.config.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/integration_test/projects/eslint-overrides.config.ts b/integration_test/projects/eslint-overrides.config.ts index 52a8809d..2211ecd1 100644 --- a/integration_test/projects/eslint-overrides.config.ts +++ b/integration_test/projects/eslint-overrides.config.ts @@ -18,17 +18,6 @@ export default tseslint.config([ config1, config2, { - languageOptions: { - parser: tseslint.parser, - sourceType: 'module', - }, - - settings: { - react: { - version: 'detect', - }, - }, - rules: { 'react/jsx-filename-extension': 'off', }, @@ -37,6 +26,8 @@ export default tseslint.config([ files: ['**/*.ts', '**/*.tsx'], // The second config should override the first if they have the same rule with the same settings. + // And then get deleted entirely in the cleanup step since it becomes redundant (off is the default + // in the default config, so the override is pointless). extends: [config1, config2], rules: { From db9df3eb79923062e7cbba06708527bf4cb8f93b Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Fri, 14 Nov 2025 00:27:11 -0700 Subject: [PATCH 6/7] Add comment --- src/cleanup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cleanup.ts b/src/cleanup.ts index 443cb9d2..e3333489 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -73,7 +73,7 @@ const cleanUpUselessOverridesEntries = (config: OxlintConfig): void => { } for (const [overrideIndex, override] of config.overrides.entries()) { - // the only key left is + // If there's only one key left, it can be deleted. An override needs files+plugins or files+rules to make sense. if (Object.keys(override).length === 1) { delete config.overrides[overrideIndex]; } From ca958d7d31ada93541c5b8e4766b6534c9f5e741 Mon Sep 17 00:00:00 2001 From: Sysix Date: Fri, 21 Nov 2025 15:24:39 +0100 Subject: [PATCH 7/7] update --- .../eslint-overrides.spec.ts.snap | 103 ------------------ integration_test/eslint-overrides.spec.ts | 5 - .../projects/eslint-overrides.config.ts | 37 ------- src/plugins_rules.ts | 23 +--- 4 files changed, 2 insertions(+), 166 deletions(-) delete mode 100644 integration_test/__snapshots__/eslint-overrides.spec.ts.snap delete mode 100644 integration_test/eslint-overrides.spec.ts delete mode 100644 integration_test/projects/eslint-overrides.config.ts diff --git a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap b/integration_test/__snapshots__/eslint-overrides.spec.ts.snap deleted file mode 100644 index 54b65e09..00000000 --- a/integration_test/__snapshots__/eslint-overrides.spec.ts.snap +++ /dev/null @@ -1,103 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`eslint-overrides > eslint-overrides 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "off", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "plugins": [ - "react", - ], - "rules": {}, - }, - "warnings": [], -} -`; - -exports[`eslint-overrides --js-plugins > eslint-overrides--js-plugins 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "off", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "plugins": [ - "react", - ], - "rules": {}, - }, - "warnings": [], -} -`; - -exports[`eslint-overrides --type-aware > eslint-overrides--type-aware 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "off", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "plugins": [ - "react", - ], - "rules": {}, - }, - "warnings": [], -} -`; - -exports[`eslint-overrides merge > eslint-overrides--merge 1`] = ` -{ - "config": { - "$schema": "./node_modules/oxlint/configuration_schema.json", - "categories": { - "correctness": "error", - "perf": "error", - }, - "env": { - "builtin": true, - }, - "ignorePatterns": [ - "node_modules/**/*", - ], - "overrides": [ - { - "files": [ - "**/*.ts", - "**/*.tsx", - ], - "rules": { - "react/react-in-jsx-scope": "off", - }, - }, - ], - "plugins": [ - "react", - ], - "rules": { - "react/react-in-jsx-scope": "error", - }, - }, - "warnings": [], -} -`; diff --git a/integration_test/eslint-overrides.spec.ts b/integration_test/eslint-overrides.spec.ts deleted file mode 100644 index f39dcd7b..00000000 --- a/integration_test/eslint-overrides.spec.ts +++ /dev/null @@ -1,5 +0,0 @@ -import eslint_overrides_test from './projects/eslint-overrides.config.js'; -import { testProject } from './utils.js'; - -// @ts-expect-error -testProject('eslint-overrides', eslint_overrides_test); diff --git a/integration_test/projects/eslint-overrides.config.ts b/integration_test/projects/eslint-overrides.config.ts deleted file mode 100644 index 2211ecd1..00000000 --- a/integration_test/projects/eslint-overrides.config.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { globalIgnores } from 'eslint/config'; -import tseslint, { type ConfigWithExtends } from 'typescript-eslint'; - -const config1: ConfigWithExtends = { - rules: { - 'react/react-in-jsx-scope': 'error', - }, -}; - -const config2: ConfigWithExtends = { - rules: { - 'react/react-in-jsx-scope': 'off', - }, -}; - -export default tseslint.config([ - globalIgnores(['node_modules/**/*']), - config1, - config2, - { - rules: { - 'react/jsx-filename-extension': 'off', - }, - }, - { - files: ['**/*.ts', '**/*.tsx'], - - // The second config should override the first if they have the same rule with the same settings. - // And then get deleted entirely in the cleanup step since it becomes redundant (off is the default - // in the default config, so the override is pointless). - extends: [config1, config2], - - rules: { - 'react/prop-types': 'off', - }, - }, -]); diff --git a/src/plugins_rules.ts b/src/plugins_rules.ts index 08eb5748..dc2cc4b0 100644 --- a/src/plugins_rules.ts +++ b/src/plugins_rules.ts @@ -196,8 +196,7 @@ export const cleanUpUselessOverridesRules = (config: OxlintConfig): void => { >(); // First pass: merge all overrides with same files pattern - for (let i = 0; i < config.overrides.length; i++) { - const override = config.overrides[i]; + for (const [i, override] of config.overrides.entries()) { if (override.files === undefined) { continue; } @@ -224,7 +223,7 @@ export const cleanUpUselessOverridesRules = (config: OxlintConfig): void => { } // Second pass: update first occurrence with merged rules and mark duplicates for deletion - for (const [_filesKey, entry] of filesPatternMap.entries()) { + for (const entry of filesPatternMap.values()) { const firstOverride = config.overrides[entry.firstIndex]; // Update the first override with the final merged rules @@ -248,24 +247,6 @@ export const cleanUpUselessOverridesRules = (config: OxlintConfig): void => { delete config.overrides[indexToRemove].rules; } } - - // Handle overrides that don't have files (just clean up rules matching root) - for (const override of config.overrides) { - if (override.files !== undefined || override.rules === undefined) { - continue; - } - - for (const [rule, settings] of Object.entries(override.rules)) { - // when they are the same, delete inside override - if (config.rules[rule] === settings) { - delete override.rules[rule]; - } - } - - if (Object.keys(override.rules).length === 0) { - delete override.rules; - } - } }; export const cleanUpRulesWhichAreCoveredByCategory = (