eslint-interactive 9.0.0 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/action/convert-error-to-warning-per-file.d.ts +6 -0
- package/dist/action/convert-error-to-warning-per-file.d.ts.map +1 -0
- package/dist/action/convert-error-to-warning-per-file.js +8 -0
- package/dist/action/convert-error-to-warning-per-file.js.map +1 -0
- package/dist/action/index.d.ts +1 -0
- package/dist/action/index.d.ts.map +1 -1
- package/dist/action/index.js +1 -0
- package/dist/action/index.js.map +1 -1
- package/dist/cli/parse-argv.d.ts.map +1 -1
- package/dist/cli/parse-argv.js +8 -1
- package/dist/cli/parse-argv.js.map +1 -1
- package/dist/cli/prompt.d.ts +2 -2
- package/dist/cli/prompt.d.ts.map +1 -1
- package/dist/cli/prompt.js +3 -2
- package/dist/cli/prompt.js.map +1 -1
- package/dist/core-worker.d.ts +1 -0
- package/dist/core-worker.d.ts.map +1 -1
- package/dist/core-worker.js +3 -0
- package/dist/core-worker.js.map +1 -1
- package/dist/core.d.ts +11 -12
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +28 -19
- package/dist/core.js.map +1 -1
- package/dist/formatter/format-by-rules.d.ts.map +1 -1
- package/dist/formatter/format-by-rules.js +1 -4
- package/dist/formatter/format-by-rules.js.map +1 -1
- package/dist/plugin/fix/convert-error-to-warning-per-file.d.ts +10 -0
- package/dist/plugin/fix/convert-error-to-warning-per-file.d.ts.map +1 -0
- package/dist/plugin/fix/convert-error-to-warning-per-file.js +29 -0
- package/dist/plugin/fix/convert-error-to-warning-per-file.js.map +1 -0
- package/dist/plugin/fix/disable-per-line.d.ts.map +1 -1
- package/dist/plugin/fix/disable-per-line.js +9 -2
- package/dist/plugin/fix/disable-per-line.js.map +1 -1
- package/dist/plugin/fix/index.d.ts +1 -0
- package/dist/plugin/fix/index.d.ts.map +1 -1
- package/dist/plugin/fix/index.js +1 -0
- package/dist/plugin/fix/index.js.map +1 -1
- package/dist/plugin/fix-rule.d.ts.map +1 -1
- package/dist/plugin/fix-rule.js +4 -1
- package/dist/plugin/fix-rule.js.map +1 -1
- package/dist/plugin/index.d.ts +6 -3
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/scene/select-action.d.ts.map +1 -1
- package/dist/scene/select-action.js +5 -1
- package/dist/scene/select-action.js.map +1 -1
- package/dist/tsconfig.src.tsbuildinfo +1 -1
- package/dist/util/cache.d.ts.map +1 -1
- package/dist/util/cache.js +1 -4
- package/dist/util/cache.js.map +1 -1
- package/dist/util/eslint.d.ts +10 -1
- package/dist/util/eslint.d.ts.map +1 -1
- package/dist/util/eslint.js +18 -0
- package/dist/util/eslint.js.map +1 -1
- package/package.json +49 -40
- package/src/action/convert-error-to-warning-per-file.ts +18 -0
- package/src/action/index.ts +1 -0
- package/src/cli/parse-argv.ts +8 -1
- package/src/cli/prompt.ts +4 -2
- package/src/core-worker.ts +5 -0
- package/src/core.ts +39 -24
- package/src/formatter/format-by-rules.ts +1 -2
- package/src/index.ts +0 -0
- package/src/plugin/fix/convert-error-to-warning-per-file.ts +45 -0
- package/src/plugin/fix/disable-per-line.ts +13 -2
- package/src/plugin/fix/index.ts +4 -0
- package/src/plugin/fix-rule.ts +3 -0
- package/src/plugin/index.ts +11 -1
- package/src/scene/select-action.ts +4 -0
- package/src/typings/cachedir.d.ts +2 -1
- package/src/util/cache.ts +1 -2
- package/src/util/eslint.ts +25 -1
package/package.json
CHANGED
|
@@ -1,68 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-interactive",
|
|
3
3
|
"description": "The CLI tool to run `eslint --fix` for each rule",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "10.2.0",
|
|
5
5
|
"repository": "https://github.com/mizdra/eslint-interactive.git",
|
|
6
6
|
"author": "mizdra <pp.mizdra@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"private": false,
|
|
9
9
|
"type": "module",
|
|
10
|
-
"exports":
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"lint:tsc:test": "tsc -p tsconfig.test.json --noEmit",
|
|
18
|
-
"lint:eslint": "eslint --ignore-pattern '/fixtures/' --ignore-pattern '/e2e-test/' .",
|
|
19
|
-
"lint:prettier": "prettier --check .",
|
|
20
|
-
"test": "FORCE_HYPERLINK=1 NODE_OPTIONS=--experimental-vm-modules jest --colors",
|
|
21
|
-
"postbuild:test": "./run-e2e-test.sh",
|
|
22
|
-
"postbuild:benchmark": "node benchmark/run.js"
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
23
17
|
},
|
|
24
18
|
"prettier": "@mizdra/prettier-config-mizdra",
|
|
25
|
-
"
|
|
19
|
+
"packageManager": "pnpm@7.5.1",
|
|
26
20
|
"devDependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
21
|
+
"@babel/core": "^7.18.13",
|
|
22
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
23
|
+
"@jest/types": "^29.0.1",
|
|
24
|
+
"@mizdra/eslint-config-mizdra": "^1.2.0",
|
|
25
|
+
"@mizdra/prettier-config-mizdra": "^1.0.0",
|
|
26
|
+
"@types/eslint": "^8.4.6",
|
|
31
27
|
"@types/estraverse": "^5.1.1",
|
|
32
|
-
"@types/estree": "^0.0
|
|
33
|
-
"@types/jest": "^
|
|
34
|
-
"@types/node": "^
|
|
28
|
+
"@types/estree": "^1.0.0",
|
|
29
|
+
"@types/jest": "^29.0.0",
|
|
30
|
+
"@types/node": "^18.0.5",
|
|
35
31
|
"@types/terminal-link": "^1.2.0",
|
|
36
|
-
"@types/yargs": "^
|
|
37
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
38
|
-
"@typescript-eslint/parser": "^5.
|
|
39
|
-
"
|
|
40
|
-
"eslint": "^8.
|
|
32
|
+
"@types/yargs": "^17.0.10",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^5.30.6",
|
|
34
|
+
"@typescript-eslint/parser": "^5.30.6",
|
|
35
|
+
"babel-jest": "^29.0.1",
|
|
36
|
+
"eslint": "^8.23.0",
|
|
41
37
|
"eslint-config-prettier": "^8.5.0",
|
|
42
|
-
"eslint-plugin-import": "^2.
|
|
43
|
-
"jest": "^
|
|
44
|
-
"jest-mock-process": "^
|
|
38
|
+
"eslint-plugin-import": "^2.26.0",
|
|
39
|
+
"jest": "^29.0.1",
|
|
40
|
+
"jest-mock-process": "^2.0.0",
|
|
45
41
|
"npm-run-all": "^4.1.5",
|
|
46
|
-
"prettier": "2.
|
|
42
|
+
"prettier": "2.7.1",
|
|
43
|
+
"resolve-from": "^5.0.0",
|
|
47
44
|
"strip-ansi": "^7.0.1",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"typescript": "^4.6.0-dev.20220211"
|
|
45
|
+
"tsc-watch": "^5.0.3",
|
|
46
|
+
"typescript": "^4.8.2"
|
|
51
47
|
},
|
|
52
48
|
"dependencies": {
|
|
53
|
-
"boxen": "^
|
|
49
|
+
"boxen": "^7.0.0",
|
|
54
50
|
"cachedir": "^2.3.0",
|
|
55
|
-
"chalk": "^5.0.
|
|
51
|
+
"chalk": "^5.0.1",
|
|
56
52
|
"comlink": "^4.3.1",
|
|
57
53
|
"enquirer": "^2.3.6",
|
|
58
54
|
"eslint-formatter-codeframe": "^7.32.1",
|
|
59
55
|
"estraverse": "^5.3.0",
|
|
60
56
|
"is-installed-globally": "^0.4.0",
|
|
61
57
|
"node-pager": "^0.3.6",
|
|
62
|
-
"ora": "^6.
|
|
58
|
+
"ora": "^6.1.2",
|
|
63
59
|
"table": "^6.8.0",
|
|
64
60
|
"terminal-link": "^3.0.0",
|
|
65
|
-
"yargs": "^
|
|
61
|
+
"yargs": "^17.5.1"
|
|
66
62
|
},
|
|
67
63
|
"peerDependencies": {
|
|
68
64
|
"eslint": "^7.0.0 || ^8.0.0"
|
|
@@ -88,5 +84,18 @@
|
|
|
88
84
|
"!src/**/__snapshots__",
|
|
89
85
|
"dist",
|
|
90
86
|
"static"
|
|
91
|
-
]
|
|
92
|
-
|
|
87
|
+
],
|
|
88
|
+
"scripts": {
|
|
89
|
+
"build": "tsc -p tsconfig.src.json",
|
|
90
|
+
"dev": "tsc-watch -p tsconfig.src.json --onSuccess 'bin/eslint-interactive.js fixtures --rulesdir fixtures/rules --ext .js,.jsx,.mjs'",
|
|
91
|
+
"lint": "run-s -c lint:*",
|
|
92
|
+
"lint:tsc": "run-s -c lint:tsc:*",
|
|
93
|
+
"lint:tsc:src": "tsc -p tsconfig.src.json --noEmit",
|
|
94
|
+
"lint:tsc:test": "tsc -p tsconfig.test.json --noEmit",
|
|
95
|
+
"lint:eslint": "eslint --ignore-pattern '/fixtures/' --ignore-pattern '/e2e-test/' .",
|
|
96
|
+
"lint:prettier": "prettier --check .",
|
|
97
|
+
"test": "FORCE_HYPERLINK=1 NODE_OPTIONS=\"--experimental-vm-modules --experimental-import-meta-resolve $NODE_OPTIONS\" jest --colors",
|
|
98
|
+
"postbuild:test": "./run-e2e-test.sh",
|
|
99
|
+
"postbuild:benchmark": "node benchmark/run.js"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Remote } from 'comlink';
|
|
2
|
+
import { ESLint } from 'eslint';
|
|
3
|
+
import { fixingSpinner } from '../cli/ora.js';
|
|
4
|
+
import { promptToInputDescription } from '../cli/prompt.js';
|
|
5
|
+
import { SerializableCore } from '../core-worker.js';
|
|
6
|
+
import { Undo } from '../core.js';
|
|
7
|
+
|
|
8
|
+
export async function doConvertErrorToWarningPerFileAction(
|
|
9
|
+
core: Remote<SerializableCore>,
|
|
10
|
+
results: ESLint.LintResult[],
|
|
11
|
+
selectedRuleIds: string[],
|
|
12
|
+
): Promise<Undo> {
|
|
13
|
+
const description = await promptToInputDescription();
|
|
14
|
+
const undo = await fixingSpinner(async () =>
|
|
15
|
+
core.convertErrorToWarningPerFile(results, selectedRuleIds, description),
|
|
16
|
+
);
|
|
17
|
+
return undo;
|
|
18
|
+
}
|
package/src/action/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { doApplySuggestionsAction } from './apply-suggestions.js';
|
|
2
2
|
export { doDisablePerFileAction } from './disable-per-file.js';
|
|
3
3
|
export { doDisablePerLineAction } from './disable-per-line.js';
|
|
4
|
+
export { doConvertErrorToWarningPerFileAction } from './convert-error-to-warning-per-file.js';
|
|
4
5
|
export { doFixAction } from './fix.js';
|
|
5
6
|
export { doMakeFixableAndFixAction } from './make-fixable-and-fix.js';
|
|
6
7
|
export { doPrintResultDetailsAction } from './print-result-details.js';
|
package/src/cli/parse-argv.ts
CHANGED
|
@@ -22,6 +22,11 @@ export function parseArgv(argv: string[]): Config {
|
|
|
22
22
|
describe: 'Specify the format to be used for the `Display problem messages` action',
|
|
23
23
|
default: DEFAULT_BASE_CONFIG.formatterName,
|
|
24
24
|
})
|
|
25
|
+
.option('quiet', {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
describe: 'Report errors only',
|
|
28
|
+
default: DEFAULT_BASE_CONFIG.quiet,
|
|
29
|
+
})
|
|
25
30
|
.option('cache', {
|
|
26
31
|
type: 'boolean',
|
|
27
32
|
describe: 'Only check changed files',
|
|
@@ -31,7 +36,8 @@ export function parseArgv(argv: string[]): Config {
|
|
|
31
36
|
type: 'string',
|
|
32
37
|
describe: `Path to the cache file or directory`,
|
|
33
38
|
default: DEFAULT_BASE_CONFIG.cacheLocation,
|
|
34
|
-
})
|
|
39
|
+
})
|
|
40
|
+
.parseSync();
|
|
35
41
|
// NOTE: convert `string` type because yargs convert `'10'` (`string` type) into `10` (`number` type)
|
|
36
42
|
// and `lintFiles` only accepts `string[]`.
|
|
37
43
|
const patterns = parsedArgv._.map((pattern) => pattern.toString());
|
|
@@ -46,6 +52,7 @@ export function parseArgv(argv: string[]): Config {
|
|
|
46
52
|
rulePaths,
|
|
47
53
|
extensions,
|
|
48
54
|
formatterName,
|
|
55
|
+
quiet: parsedArgv.quiet,
|
|
49
56
|
cache: parsedArgv.cache,
|
|
50
57
|
cacheLocation: parsedArgv['cache-location'],
|
|
51
58
|
};
|
package/src/cli/prompt.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type Action =
|
|
|
18
18
|
| 'applyAutoFixes'
|
|
19
19
|
| 'disablePerLine'
|
|
20
20
|
| 'disablePerFile'
|
|
21
|
+
| 'convertErrorToWarningPerFile'
|
|
21
22
|
| 'applySuggestions'
|
|
22
23
|
| 'makeFixableAndFix'
|
|
23
24
|
| 'reselectRules';
|
|
@@ -82,6 +83,7 @@ export async function promptToInputAction(
|
|
|
82
83
|
{ name: 'applyAutoFixes', message: '🔧 Run `eslint --fix`', disabled: foldedStatistics.isFixableCount === 0 },
|
|
83
84
|
{ name: 'disablePerLine', message: '🔧 Disable per line' },
|
|
84
85
|
{ name: 'disablePerFile', message: '🔧 Disable per file' },
|
|
86
|
+
{ name: 'convertErrorToWarningPerFile', message: '🔧 Convert error to warning per file' },
|
|
85
87
|
{
|
|
86
88
|
name: 'applySuggestions',
|
|
87
89
|
message: '🔧 Apply suggestions (experimental, for experts)',
|
|
@@ -132,7 +134,7 @@ export async function promptToInputDisplayMode(): Promise<DisplayMode> {
|
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
/**
|
|
135
|
-
* Ask the user a description to leave in
|
|
137
|
+
* Ask the user a description to leave in directive.
|
|
136
138
|
* @returns The description
|
|
137
139
|
*/
|
|
138
140
|
export async function promptToInputDescription(): Promise<string | undefined> {
|
|
@@ -142,7 +144,7 @@ export async function promptToInputDescription(): Promise<string | undefined> {
|
|
|
142
144
|
{
|
|
143
145
|
name: 'description',
|
|
144
146
|
type: 'input',
|
|
145
|
-
message: 'Leave a code comment with your reason for
|
|
147
|
+
message: 'Leave a code comment with your reason for fixing (Optional)',
|
|
146
148
|
onCancel,
|
|
147
149
|
},
|
|
148
150
|
]);
|
package/src/core-worker.ts
CHANGED
|
@@ -40,6 +40,11 @@ export class SerializableCore {
|
|
|
40
40
|
async disablePerFile(...args: Parameters<Core['disablePerFile']>): ReturnType<Core['disablePerFile']> {
|
|
41
41
|
return proxy(await this.core.disablePerFile(...args));
|
|
42
42
|
}
|
|
43
|
+
async convertErrorToWarningPerFile(
|
|
44
|
+
...args: Parameters<Core['convertErrorToWarningPerFile']>
|
|
45
|
+
): ReturnType<Core['convertErrorToWarningPerFile']> {
|
|
46
|
+
return proxy(await this.core.convertErrorToWarningPerFile(...args));
|
|
47
|
+
}
|
|
43
48
|
async applySuggestions(
|
|
44
49
|
results: ESLint.LintResult[],
|
|
45
50
|
ruleIds: string[],
|
package/src/core.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import { ESLint } from 'eslint';
|
|
4
|
-
|
|
5
|
-
import isInstalledGlobally = require('is-installed-globally');
|
|
4
|
+
import isInstalledGlobally from 'is-installed-globally';
|
|
6
5
|
import { format } from './formatter/index.js';
|
|
7
6
|
import {
|
|
8
7
|
eslintInteractivePlugin,
|
|
@@ -51,21 +50,24 @@ async function getUsedRuleIds(targetFilePaths: string[], options: ESLint.Options
|
|
|
51
50
|
export type Undo = () => Promise<void>;
|
|
52
51
|
|
|
53
52
|
/** The config of eslint-interactive */
|
|
54
|
-
export type Config =
|
|
53
|
+
export type Config = Pick<
|
|
54
|
+
ESLint.Options,
|
|
55
|
+
'extensions' | 'rulePaths' | 'cache' | 'cacheLocation' | 'useEslintrc' | 'overrideConfig' | 'cwd'
|
|
56
|
+
> & {
|
|
55
57
|
patterns: string[];
|
|
56
|
-
rulePaths?: string[] | undefined;
|
|
57
|
-
extensions?: string[] | undefined;
|
|
58
58
|
formatterName?: string;
|
|
59
|
-
|
|
60
|
-
cacheLocation?: string;
|
|
61
|
-
cwd?: string;
|
|
59
|
+
quiet?: boolean;
|
|
62
60
|
};
|
|
63
61
|
|
|
64
62
|
/** Default config of `Core` */
|
|
65
|
-
export const DEFAULT_BASE_CONFIG = {
|
|
63
|
+
export const DEFAULT_BASE_CONFIG: Partial<Config> = {
|
|
64
|
+
cwd: undefined,
|
|
66
65
|
cache: true,
|
|
67
66
|
cacheLocation: join(getCacheDir(), '.eslintcache'),
|
|
67
|
+
extensions: undefined,
|
|
68
68
|
formatterName: 'codeframe',
|
|
69
|
+
quiet: false,
|
|
70
|
+
rulePaths: undefined,
|
|
69
71
|
};
|
|
70
72
|
|
|
71
73
|
/**
|
|
@@ -75,17 +77,15 @@ export const DEFAULT_BASE_CONFIG = {
|
|
|
75
77
|
export class Core {
|
|
76
78
|
readonly config: Config;
|
|
77
79
|
/** The base options of ESLint */
|
|
78
|
-
readonly
|
|
80
|
+
readonly baseESLintOptions: ESLint.Options;
|
|
79
81
|
|
|
80
82
|
constructor(config: Config) {
|
|
81
|
-
this.config =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
cacheLocation: this.config.cacheLocation ?? DEFAULT_BASE_CONFIG.cacheLocation,
|
|
85
|
-
rulePaths: this.config.rulePaths,
|
|
86
|
-
extensions: this.config.extensions,
|
|
87
|
-
cwd: this.config.cwd,
|
|
83
|
+
this.config = {
|
|
84
|
+
...DEFAULT_BASE_CONFIG,
|
|
85
|
+
...config,
|
|
88
86
|
};
|
|
87
|
+
const { patterns, formatterName, quiet, ...baseOptions } = this.config;
|
|
88
|
+
this.baseESLintOptions = baseOptions;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
@@ -93,8 +93,9 @@ export class Core {
|
|
|
93
93
|
* @returns The results of linting
|
|
94
94
|
*/
|
|
95
95
|
async lint(): Promise<ESLint.LintResult[]> {
|
|
96
|
-
const eslint = new ESLint(this.
|
|
97
|
-
|
|
96
|
+
const eslint = new ESLint(this.baseESLintOptions);
|
|
97
|
+
let results = await eslint.lintFiles(this.config.patterns);
|
|
98
|
+
if (this.config.quiet) results = ESLint.getErrorResults(results);
|
|
98
99
|
return results;
|
|
99
100
|
}
|
|
100
101
|
|
|
@@ -108,8 +109,8 @@ export class Core {
|
|
|
108
109
|
|
|
109
110
|
// get `rulesMeta` from `results`
|
|
110
111
|
const eslint = new ESLint({
|
|
111
|
-
...this.
|
|
112
|
-
overrideConfig: { plugins },
|
|
112
|
+
...this.baseESLintOptions,
|
|
113
|
+
overrideConfig: { ...this.baseESLintOptions.overrideConfig, plugins },
|
|
113
114
|
});
|
|
114
115
|
// NOTE: `getRulesMetaForResults` is a feature added in ESLint 7.29.0.
|
|
115
116
|
// Therefore, the function may not exist in versions lower than 7.29.0.
|
|
@@ -124,7 +125,7 @@ export class Core {
|
|
|
124
125
|
* @param ruleIds The rule ids to print details
|
|
125
126
|
*/
|
|
126
127
|
async formatResultDetails(results: ESLint.LintResult[], ruleIds: (string | null)[]): Promise<string> {
|
|
127
|
-
const eslint = new ESLint(this.
|
|
128
|
+
const eslint = new ESLint(this.baseESLintOptions);
|
|
128
129
|
const formatterName = this.config.formatterName ?? DEFAULT_BASE_CONFIG.formatterName;
|
|
129
130
|
|
|
130
131
|
// When eslint-interactive is installed globally, eslint-formatter-codeframe will also be installed globally.
|
|
@@ -173,6 +174,20 @@ export class Core {
|
|
|
173
174
|
return await this.fix(results, ruleIds, { name: 'disablePerFile', args: { description } });
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Convert error to warning per file.
|
|
179
|
+
* @param results The lint results of the project to convert
|
|
180
|
+
* @param ruleIds The rule ids to convert
|
|
181
|
+
* @param description The comment explaining the reason for converting
|
|
182
|
+
*/
|
|
183
|
+
async convertErrorToWarningPerFile(
|
|
184
|
+
results: ESLint.LintResult[],
|
|
185
|
+
ruleIds: string[],
|
|
186
|
+
description?: string,
|
|
187
|
+
): Promise<Undo> {
|
|
188
|
+
return await this.fix(results, ruleIds, { name: 'convertErrorToWarningPerFile', args: { description } });
|
|
189
|
+
}
|
|
190
|
+
|
|
176
191
|
/**
|
|
177
192
|
* Apply suggestions.
|
|
178
193
|
* @param results The lint results of the project to apply suggestions
|
|
@@ -201,13 +216,13 @@ export class Core {
|
|
|
201
216
|
// NOTE: Extract only necessary results and files for performance
|
|
202
217
|
const filteredResultsOfLint = filterResultsByRuleId(resultsOfLint, ruleIds);
|
|
203
218
|
const targetFilePaths = filteredResultsOfLint.map((result) => result.filePath);
|
|
204
|
-
const usedRuleIds = await getUsedRuleIds(targetFilePaths, this.
|
|
219
|
+
const usedRuleIds = await getUsedRuleIds(targetFilePaths, this.baseESLintOptions);
|
|
205
220
|
|
|
206
221
|
// TODO: refactor
|
|
207
222
|
let results = filteredResultsOfLint;
|
|
208
223
|
for (let i = 0; i < MAX_AUTOFIX_PASSES; i++) {
|
|
209
224
|
const eslint = new ESLint({
|
|
210
|
-
...this.
|
|
225
|
+
...this.baseESLintOptions,
|
|
211
226
|
// This is super hack to load ESM plugin/rule.
|
|
212
227
|
// ref: https://github.com/eslint/eslint/issues/15453#issuecomment-1001200953
|
|
213
228
|
plugins: {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { ESLint } from 'eslint';
|
|
3
|
-
|
|
4
|
-
import table = require('table');
|
|
3
|
+
import table from 'table';
|
|
5
4
|
import terminalLink from 'terminal-link';
|
|
6
5
|
import { ERROR_COLOR } from './colors.js';
|
|
7
6
|
import { takeRuleStatistics } from './take-rule-statistics.js';
|
package/src/index.ts
CHANGED
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Rule, Linter } from 'eslint';
|
|
2
|
+
import { unique } from '../../util/array.js';
|
|
3
|
+
import { findShebang, toInlineConfigCommentText } from '../../util/eslint.js';
|
|
4
|
+
import { notEmpty } from '../../util/type-check.js';
|
|
5
|
+
import { FixContext } from '../index.js';
|
|
6
|
+
|
|
7
|
+
export type FixToConvertErrorToWarningPerFileArgs = {
|
|
8
|
+
description?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function generateFix(context: FixContext, description?: string): Rule.Fix | null {
|
|
12
|
+
const ruleIdsToConverting = unique(
|
|
13
|
+
context.messages
|
|
14
|
+
// Ignore warnings
|
|
15
|
+
.filter((message) => message.severity === 2)
|
|
16
|
+
.map((message) => message.ruleId)
|
|
17
|
+
.filter(notEmpty),
|
|
18
|
+
);
|
|
19
|
+
if (ruleIdsToConverting.length === 0) return null;
|
|
20
|
+
|
|
21
|
+
const rulesRecordToConverting: Partial<Linter.RulesRecord> = Object.fromEntries(
|
|
22
|
+
ruleIdsToConverting.map((ruleId) => [ruleId, 1]),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// Insert the inline config comment at the top of the file.
|
|
26
|
+
// NOTE: Merging settings into an existing inline config comment is intentionally avoided
|
|
27
|
+
// because of the complexity of the implementation.
|
|
28
|
+
|
|
29
|
+
const text = toInlineConfigCommentText({ rulesRecord: rulesRecordToConverting, description }) + '\n';
|
|
30
|
+
|
|
31
|
+
const shebang = findShebang(context.sourceCode.text);
|
|
32
|
+
// if shebang exists, insert comment after shebang
|
|
33
|
+
return context.fixer.insertTextAfterRange(shebang?.range ?? [0, 0], text);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create fix to convert error to warning per file.
|
|
38
|
+
*/
|
|
39
|
+
export function createFixToConvertErrorToWarningPerFile(
|
|
40
|
+
context: FixContext,
|
|
41
|
+
args: FixToConvertErrorToWarningPerFileArgs,
|
|
42
|
+
): Rule.Fix[] {
|
|
43
|
+
const fix = generateFix(context, args.description);
|
|
44
|
+
return fix ? [fix] : [];
|
|
45
|
+
}
|
|
@@ -40,13 +40,24 @@ function generateFixPerLine(
|
|
|
40
40
|
const headNode = context.sourceCode.getNodeByRangeIndex(headNodeIndex);
|
|
41
41
|
if (headNode === null) return null; // For some reason, it seems to be null sometimes.
|
|
42
42
|
|
|
43
|
+
// Extract the same indent as the line we want to fix
|
|
44
|
+
const indent = context.sourceCode.text.slice(
|
|
45
|
+
headNodeIndex,
|
|
46
|
+
headNodeIndex +
|
|
47
|
+
context.sourceCode.text
|
|
48
|
+
.slice(headNodeIndex)
|
|
49
|
+
// ref: https://tc39.es/ecma262/#sec-white-space
|
|
50
|
+
// eslint-disable-next-line no-control-regex
|
|
51
|
+
.search(/[^\u{0009}\u{000B}\u{000C}\u{FEFF}\p{gc=Space_Separator}]/u),
|
|
52
|
+
);
|
|
53
|
+
|
|
43
54
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
55
|
if ((headNode.type as any) === 'JSXText') {
|
|
45
56
|
const commentText = toCommentText({ type: 'Block', scope: 'next-line', ruleIds: ruleIdsToDisable, description });
|
|
46
|
-
return context.fixer.insertTextBeforeRange([headNodeIndex, headNodeIndex], '{' + commentText + '}\n');
|
|
57
|
+
return context.fixer.insertTextBeforeRange([headNodeIndex, headNodeIndex], indent + '{' + commentText + '}\n');
|
|
47
58
|
} else {
|
|
48
59
|
const commentText = toCommentText({ type: 'Line', scope: 'next-line', ruleIds: ruleIdsToDisable, description });
|
|
49
|
-
return context.fixer.insertTextBeforeRange([headNodeIndex, headNodeIndex], commentText + '\n');
|
|
60
|
+
return context.fixer.insertTextBeforeRange([headNodeIndex, headNodeIndex], indent + commentText + '\n');
|
|
50
61
|
}
|
|
51
62
|
}
|
|
52
63
|
}
|
package/src/plugin/fix/index.ts
CHANGED
|
@@ -6,6 +6,10 @@ export {
|
|
|
6
6
|
export { type FixToApplyAutoFixesArgs, createFixToApplyAutoFixes } from './apply-auto-fixes.js';
|
|
7
7
|
export { type FixToDisablePerFileArgs, createFixToDisablePerFile } from './disable-per-file.js';
|
|
8
8
|
export { type FixToDisablePerLineArgs, createFixToDisablePerLine } from './disable-per-line.js';
|
|
9
|
+
export {
|
|
10
|
+
type FixToConvertErrorToWarningPerFileArgs,
|
|
11
|
+
createFixToConvertErrorToWarningPerFile,
|
|
12
|
+
} from './convert-error-to-warning-per-file.js';
|
|
9
13
|
export {
|
|
10
14
|
type FixableMaker,
|
|
11
15
|
type FixToMakeFixableAndFixArgs,
|
package/src/plugin/fix-rule.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ESLint, Rule } from 'eslint';
|
|
|
2
2
|
import {
|
|
3
3
|
createFixToApplyAutoFixes,
|
|
4
4
|
createFixToApplySuggestions,
|
|
5
|
+
createFixToConvertErrorToWarningPerFile,
|
|
5
6
|
createFixToDisablePerFile,
|
|
6
7
|
createFixToDisablePerLine,
|
|
7
8
|
createFixToMakeFixableAndFix,
|
|
@@ -53,6 +54,8 @@ function createFixes(context: Rule.RuleContext, ruleOption: FixRuleOption, fixer
|
|
|
53
54
|
fixes = createFixToDisablePerLine(fixContext, fix.args);
|
|
54
55
|
} else if (fix.name === 'disablePerFile') {
|
|
55
56
|
fixes = createFixToDisablePerFile(fixContext, fix.args);
|
|
57
|
+
} else if (fix.name === 'convertErrorToWarningPerFile') {
|
|
58
|
+
fixes = createFixToConvertErrorToWarningPerFile(fixContext, fix.args);
|
|
56
59
|
} else if (fix.name === 'applySuggestions') {
|
|
57
60
|
fixes = createFixToApplySuggestions(fixContext, fix.args);
|
|
58
61
|
} else if (fix.name === 'makeFixableAndFix') {
|
package/src/plugin/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type FixToDisablePerLineArgs,
|
|
9
9
|
type FixToMakeFixableAndFixArgs,
|
|
10
10
|
type FixToApplyAutoFixesArgs,
|
|
11
|
+
FixToConvertErrorToWarningPerFileArgs,
|
|
11
12
|
} from './fix/index.js';
|
|
12
13
|
import { preferAdditionShorthandRule } from './prefer-addition-shorthand-rule.js';
|
|
13
14
|
|
|
@@ -30,11 +31,18 @@ export type Fix =
|
|
|
30
31
|
| { name: 'applyAutoFixes'; args: FixArg<'applyAutoFixes'> }
|
|
31
32
|
| { name: 'disablePerLine'; args: FixArg<'disablePerLine'> }
|
|
32
33
|
| { name: 'disablePerFile'; args: FixArg<'disablePerFile'> }
|
|
34
|
+
| { name: 'convertErrorToWarningPerFile'; args: FixArg<'convertErrorToWarningPerFile'> }
|
|
33
35
|
| { name: 'applySuggestions'; args: FixArg<'applySuggestions'> }
|
|
34
36
|
| { name: 'makeFixableAndFix'; args: FixArg<'makeFixableAndFix'> };
|
|
35
37
|
|
|
36
38
|
/** For test */
|
|
37
|
-
export type FixName =
|
|
39
|
+
export type FixName =
|
|
40
|
+
| 'applyAutoFixes'
|
|
41
|
+
| 'disablePerLine'
|
|
42
|
+
| 'disablePerFile'
|
|
43
|
+
| 'convertErrorToWarningPerFile'
|
|
44
|
+
| 'applySuggestions'
|
|
45
|
+
| 'makeFixableAndFix';
|
|
38
46
|
|
|
39
47
|
/** For test */
|
|
40
48
|
export type FixArg<T extends FixName> = T extends 'applyAutoFixes'
|
|
@@ -43,6 +51,8 @@ export type FixArg<T extends FixName> = T extends 'applyAutoFixes'
|
|
|
43
51
|
? FixToDisablePerLineArgs
|
|
44
52
|
: T extends 'disablePerFile'
|
|
45
53
|
? FixToDisablePerFileArgs
|
|
54
|
+
: T extends 'convertErrorToWarningPerFile'
|
|
55
|
+
? FixToConvertErrorToWarningPerFileArgs
|
|
46
56
|
: T extends 'applySuggestions'
|
|
47
57
|
? FixToApplySuggestionsArgs
|
|
48
58
|
: T extends 'makeFixableAndFix'
|
|
@@ -2,6 +2,7 @@ import { Remote } from 'comlink';
|
|
|
2
2
|
import { ESLint } from 'eslint';
|
|
3
3
|
import {
|
|
4
4
|
doApplySuggestionsAction,
|
|
5
|
+
doConvertErrorToWarningPerFileAction,
|
|
5
6
|
doDisablePerFileAction,
|
|
6
7
|
doDisablePerLineAction,
|
|
7
8
|
doFixAction,
|
|
@@ -58,6 +59,9 @@ export async function selectAction(
|
|
|
58
59
|
} else if (selectedAction === 'disablePerFile') {
|
|
59
60
|
const undo = await doDisablePerFileAction(core, results, selectedRuleIds);
|
|
60
61
|
return createCheckResultsScene(undo);
|
|
62
|
+
} else if (selectedAction === 'convertErrorToWarningPerFile') {
|
|
63
|
+
const undo = await doConvertErrorToWarningPerFileAction(core, results, selectedRuleIds);
|
|
64
|
+
return createCheckResultsScene(undo);
|
|
61
65
|
} else if (selectedAction === 'applySuggestions') {
|
|
62
66
|
const undo = await doApplySuggestionsAction(core, results, selectedRuleIds);
|
|
63
67
|
return createCheckResultsScene(undo);
|
package/src/util/cache.ts
CHANGED
package/src/util/eslint.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AST, ESLint } from 'eslint';
|
|
1
|
+
import { AST, ESLint, Linter } from 'eslint';
|
|
2
2
|
import type { Comment } from 'estree';
|
|
3
3
|
import { unique } from './array.js';
|
|
4
4
|
import { notEmpty } from './type-check.js';
|
|
@@ -97,6 +97,30 @@ export function toCommentText({ type, scope, ruleIds, description }: Omit<Disabl
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export type InlineConfigComment = {
|
|
101
|
+
description?: string;
|
|
102
|
+
rulesRecord: Partial<Linter.RulesRecord>;
|
|
103
|
+
range: [number, number];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Convert `InlineConfigComment` to comment text.
|
|
108
|
+
*/
|
|
109
|
+
export function toInlineConfigCommentText({ rulesRecord, description }: Omit<InlineConfigComment, 'range'>): string {
|
|
110
|
+
const header = 'eslint';
|
|
111
|
+
const rulesRecordText = Object.entries(rulesRecord)
|
|
112
|
+
.map(([ruleId, ruleEntry]) => {
|
|
113
|
+
// TODO: Inherit options of the rule set by the user in eslintrc if the option exists.
|
|
114
|
+
return `${ruleId}: ${JSON.stringify(ruleEntry)}`;
|
|
115
|
+
})
|
|
116
|
+
.join(', ');
|
|
117
|
+
if (description === undefined) {
|
|
118
|
+
return `/* ${header} ${rulesRecordText} */`;
|
|
119
|
+
} else {
|
|
120
|
+
return `/* ${header} ${rulesRecordText} -- ${description} */`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
/**
|
|
101
125
|
* Create the results with only messages with the specified rule ids.
|
|
102
126
|
* @param results The lint results.
|