ignore-lint-errors 0.6.0 → 0.8.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 +27 -0
- package/dist/bin/ignore-lint-errors.js +6 -0
- package/dist/src/steps/create-options.js +3 -3
- package/dist/src/steps/lint-files/eslint.js +35 -0
- package/dist/src/steps/lint-files/stylelint.js +9 -2
- package/dist/src/utils/ignore-errors/eslint.js +7 -29
- package/dist/src/utils/ignore-errors/shared/index.js +24 -0
- package/dist/src/utils/ignore-errors/stylelint.js +7 -29
- package/dist/src/utils/ignore-errors/typescript.js +58 -22
- package/dist/src/utils/linters/eslint.js +16 -33
- package/dist/src/utils/linters/shared/index.js +29 -0
- package/dist/src/utils/linters/stylelint.js +16 -33
- package/dist/src/utils/linters/typescript.js +10 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,33 @@ pnpx ignore-lint-errors --root <path/to/your/project>
|
|
|
65
65
|
|
|
66
66
|
</details>
|
|
67
67
|
|
|
68
|
+
<details>
|
|
69
|
+
|
|
70
|
+
<summary>Optional: Specify files to lint</summary>
|
|
71
|
+
|
|
72
|
+
Pass `--src` to lint specific files.
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
# eslint supports files
|
|
76
|
+
pnpx ignore-lint-errors --linter eslint --src app/components/example-1.gts app/templates/example-2.gts
|
|
77
|
+
|
|
78
|
+
# eslint supports directories
|
|
79
|
+
pnpx ignore-lint-errors --linter eslint --src app tests
|
|
80
|
+
|
|
81
|
+
# eslint supports globs
|
|
82
|
+
pnpx ignore-lint-errors --linter eslint --src app/{components,templates}/**/*.gts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
# stylelint supports files
|
|
87
|
+
pnpx ignore-lint-errors --linter stylelint --src app/components/example-1.module.css app/templates/example-2.module.css
|
|
88
|
+
|
|
89
|
+
# stylelint supports globs
|
|
90
|
+
pnpx ignore-lint-errors --linter stylelint --src **/*.scss
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
</details>
|
|
94
|
+
|
|
68
95
|
|
|
69
96
|
### Limitations
|
|
70
97
|
|
|
@@ -15,11 +15,17 @@ const argv = yargs(hideBin(process.argv))
|
|
|
15
15
|
.option('root', {
|
|
16
16
|
describe: 'Where to run the codemod',
|
|
17
17
|
type: 'string',
|
|
18
|
+
})
|
|
19
|
+
.option('src', {
|
|
20
|
+
describe: 'Locations of files to lint',
|
|
21
|
+
string: true,
|
|
22
|
+
type: 'array',
|
|
18
23
|
})
|
|
19
24
|
.demandOption(['linter'])
|
|
20
25
|
.parseSync();
|
|
21
26
|
const codemodOptions = {
|
|
22
27
|
linter: argv['linter'],
|
|
23
28
|
projectRoot: argv['root'] ?? process.cwd(),
|
|
29
|
+
src: argv['src'],
|
|
24
30
|
};
|
|
25
31
|
runCodemod(codemodOptions);
|
|
@@ -7,17 +7,17 @@ function findDependencies(projectRoot) {
|
|
|
7
7
|
]);
|
|
8
8
|
return {
|
|
9
9
|
eslint: projectDependencies.has('eslint'),
|
|
10
|
-
glint: projectDependencies.has('@glint/
|
|
11
|
-
projectDependencies.has('@glint/ember-tsc'),
|
|
10
|
+
glint: projectDependencies.has('@glint/ember-tsc'),
|
|
12
11
|
stylelint: projectDependencies.has('stylelint'),
|
|
13
12
|
typescript: projectDependencies.has('typescript'),
|
|
14
13
|
};
|
|
15
14
|
}
|
|
16
15
|
export function createOptions(codemodOptions) {
|
|
17
|
-
const { linter, projectRoot } = codemodOptions;
|
|
16
|
+
const { linter, projectRoot, src } = codemodOptions;
|
|
18
17
|
return {
|
|
19
18
|
dependencies: findDependencies(projectRoot),
|
|
20
19
|
linter,
|
|
21
20
|
projectRoot,
|
|
21
|
+
src,
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -1,9 +1,44 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
+
import { findFiles } from '@codemod-utils/files';
|
|
2
3
|
import { outputFilePath } from '../../utils/linters/eslint.js';
|
|
4
|
+
function getConcurrencyOption(options) {
|
|
5
|
+
const { projectRoot } = options;
|
|
6
|
+
let isConcurrencySupported = true;
|
|
7
|
+
try {
|
|
8
|
+
const command = [
|
|
9
|
+
'./node_modules/.bin/eslint does-not-exist.js',
|
|
10
|
+
'--concurrency off',
|
|
11
|
+
'--no-error-on-unmatched-pattern',
|
|
12
|
+
'2>/dev/null', // Suppress output to process.stderr
|
|
13
|
+
].join(' ');
|
|
14
|
+
execSync(command, { cwd: projectRoot });
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
isConcurrencySupported = false;
|
|
18
|
+
}
|
|
19
|
+
if (!isConcurrencySupported) {
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
const filePaths = findFiles('**/*.{gjs,gts,js,ts}', {
|
|
23
|
+
ignoreList: ['{dist,node_modules}/**/*', '**/*.d.ts'],
|
|
24
|
+
projectRoot,
|
|
25
|
+
});
|
|
26
|
+
const concurrency = Math.max(Math.ceil(Math.log10(filePaths.length)), 1);
|
|
27
|
+
return `--concurrency ${concurrency}`;
|
|
28
|
+
}
|
|
29
|
+
function getSrc(options) {
|
|
30
|
+
const { src } = options;
|
|
31
|
+
if (src === undefined) {
|
|
32
|
+
return '.';
|
|
33
|
+
}
|
|
34
|
+
return src.map((token) => `"${token}"`).join(' ');
|
|
35
|
+
}
|
|
3
36
|
export function runEslint(options) {
|
|
4
37
|
const { projectRoot } = options;
|
|
5
38
|
const command = [
|
|
6
39
|
'./node_modules/.bin/eslint',
|
|
40
|
+
getSrc(options),
|
|
41
|
+
getConcurrencyOption(options),
|
|
7
42
|
'--format json',
|
|
8
43
|
`--output-file ${outputFilePath}`,
|
|
9
44
|
'--quiet',
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { outputFilePath } from '../../utils/linters/stylelint.js';
|
|
3
|
+
function getSrc(options) {
|
|
4
|
+
const { src } = options;
|
|
5
|
+
if (src === undefined) {
|
|
6
|
+
return '**/*.css';
|
|
7
|
+
}
|
|
8
|
+
return src.map((token) => `"${token}"`).join(' ');
|
|
9
|
+
}
|
|
3
10
|
export function runStylelint(options) {
|
|
4
11
|
const { projectRoot } = options;
|
|
5
12
|
const command = [
|
|
6
|
-
'./node_modules/.bin/stylelint
|
|
7
|
-
|
|
13
|
+
'./node_modules/.bin/stylelint',
|
|
14
|
+
getSrc(options),
|
|
8
15
|
'--formatter json',
|
|
9
16
|
`--output-file ${outputFilePath}`,
|
|
10
17
|
'--quiet',
|
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
|
-
import {
|
|
3
|
-
function getIgnoredRules(lineOfCode) {
|
|
4
|
-
const traverse = AST.traverse(true);
|
|
5
|
-
let ignoredRules = [];
|
|
6
|
-
try {
|
|
7
|
-
traverse(lineOfCode, {
|
|
8
|
-
visitComment(node) {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
10
|
-
const comment = node.value.value.trim();
|
|
11
|
-
if (comment.startsWith('eslint-disable-next-line')) {
|
|
12
|
-
ignoredRules = comment
|
|
13
|
-
.replace(/^eslint-disable-next-line\s+/, '')
|
|
14
|
-
.split(',')
|
|
15
|
-
.map((token) => token.trim());
|
|
16
|
-
}
|
|
17
|
-
return false;
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
// Do nothing
|
|
23
|
-
}
|
|
24
|
-
return ignoredRules;
|
|
25
|
-
}
|
|
2
|
+
import { getIgnoredRules } from './shared/index.js';
|
|
26
3
|
export function ignoreErrors(file, lintErrors) {
|
|
27
4
|
const lines = file.split(EOL);
|
|
5
|
+
const ignoreDirective = 'eslint-disable-next-line';
|
|
28
6
|
lintErrors.forEach(({ line, message }) => {
|
|
29
7
|
const currentIndex = line - 1;
|
|
30
8
|
const previousIndex = Math.max(currentIndex - 1, 0);
|
|
31
|
-
const ignoredRules = getIgnoredRules(lines[previousIndex]
|
|
9
|
+
const ignoredRules = getIgnoredRules(lines[previousIndex], {
|
|
10
|
+
ignoreDirective,
|
|
11
|
+
});
|
|
32
12
|
if (ignoredRules.length === 0) {
|
|
33
|
-
|
|
34
|
-
lines.splice(currentIndex, 0, ignoreDirective);
|
|
13
|
+
lines.splice(currentIndex, 0, `// ${ignoreDirective} ${message}`);
|
|
35
14
|
}
|
|
36
15
|
else {
|
|
37
16
|
const newMessage = [...ignoredRules, ...message.split(', ')]
|
|
38
17
|
.sort()
|
|
39
18
|
.join(', ');
|
|
40
|
-
|
|
41
|
-
lines.splice(previousIndex, 1, ignoreDirective);
|
|
19
|
+
lines.splice(previousIndex, 1, `// ${ignoreDirective} ${newMessage}`);
|
|
42
20
|
}
|
|
43
21
|
});
|
|
44
22
|
return lines.join(EOL);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AST } from '@codemod-utils/ast-javascript';
|
|
2
|
+
export function getIgnoredRules(lineOfCode, options) {
|
|
3
|
+
const traverse = AST.traverse(true);
|
|
4
|
+
let ignoredRules = [];
|
|
5
|
+
try {
|
|
6
|
+
traverse(lineOfCode, {
|
|
7
|
+
visitComment(node) {
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
9
|
+
const comment = node.value.value.trim();
|
|
10
|
+
if (comment.startsWith(options.ignoreDirective)) {
|
|
11
|
+
ignoredRules = comment
|
|
12
|
+
.replace(new RegExp(`^${options.ignoreDirective}\\s+`, 'g'), '')
|
|
13
|
+
.split(',')
|
|
14
|
+
.map((token) => token.trim());
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Do nothing
|
|
22
|
+
}
|
|
23
|
+
return ignoredRules;
|
|
24
|
+
}
|
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
|
-
import {
|
|
3
|
-
function getIgnoredRules(lineOfCode) {
|
|
4
|
-
const traverse = AST.traverse(true);
|
|
5
|
-
let ignoredRules = [];
|
|
6
|
-
try {
|
|
7
|
-
traverse(lineOfCode, {
|
|
8
|
-
visitComment(node) {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
10
|
-
const comment = node.value.value.trim();
|
|
11
|
-
if (comment.startsWith('stylelint-disable-next-line')) {
|
|
12
|
-
ignoredRules = comment
|
|
13
|
-
.replace(/^stylelint-disable-next-line\s+/, '')
|
|
14
|
-
.split(',')
|
|
15
|
-
.map((token) => token.trim());
|
|
16
|
-
}
|
|
17
|
-
return false;
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
// Do nothing
|
|
23
|
-
}
|
|
24
|
-
return ignoredRules;
|
|
25
|
-
}
|
|
2
|
+
import { getIgnoredRules } from './shared/index.js';
|
|
26
3
|
export function ignoreErrors(file, lintErrors) {
|
|
27
4
|
const lines = file.split(EOL);
|
|
5
|
+
const ignoreDirective = 'stylelint-disable-next-line';
|
|
28
6
|
lintErrors.forEach(({ line, message }) => {
|
|
29
7
|
const currentIndex = line - 1;
|
|
30
8
|
const previousIndex = Math.max(currentIndex - 1, 0);
|
|
31
|
-
const ignoredRules = getIgnoredRules(lines[previousIndex]
|
|
9
|
+
const ignoredRules = getIgnoredRules(lines[previousIndex], {
|
|
10
|
+
ignoreDirective,
|
|
11
|
+
});
|
|
32
12
|
if (ignoredRules.length === 0) {
|
|
33
|
-
|
|
34
|
-
lines.splice(currentIndex, 0, ignoreDirective);
|
|
13
|
+
lines.splice(currentIndex, 0, `/* ${ignoreDirective} ${message} */`);
|
|
35
14
|
}
|
|
36
15
|
else {
|
|
37
16
|
const newMessage = [...ignoredRules, ...message.split(', ')]
|
|
38
17
|
.sort()
|
|
39
18
|
.join(', ');
|
|
40
|
-
|
|
41
|
-
lines.splice(previousIndex, 1, ignoreDirective);
|
|
19
|
+
lines.splice(previousIndex, 1, `/* ${ignoreDirective} ${newMessage} */`);
|
|
42
20
|
}
|
|
43
21
|
});
|
|
44
22
|
return lines.join(EOL);
|
|
@@ -1,56 +1,92 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
2
|
import { AST } from '@codemod-utils/ast-template';
|
|
3
|
-
import { findTemplateTags, updateTemplates, } from '@codemod-utils/ast-template-tag';
|
|
4
|
-
|
|
3
|
+
import { findTemplateTags as upstreamFindTemplateTags, updateTemplates, } from '@codemod-utils/ast-template-tag';
|
|
4
|
+
import { getIgnoredRules } from './shared/index.js';
|
|
5
|
+
function findTemplateTags(file) {
|
|
5
6
|
function getLOC(file) {
|
|
6
7
|
const matches = file.match(/\r?\n/g);
|
|
7
8
|
return (matches ?? []).length;
|
|
8
9
|
}
|
|
9
|
-
const templateTags =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const { range } = templateTag;
|
|
10
|
+
const templateTags = upstreamFindTemplateTags(file);
|
|
11
|
+
return templateTags.map((templateTag) => {
|
|
12
|
+
const { contents, range } = templateTag;
|
|
13
13
|
const lineStart = getLOC(file.substring(0, range.startChar)) + 1;
|
|
14
14
|
const lineEnd = getLOC(file.substring(0, range.endChar)) + 1;
|
|
15
|
-
|
|
15
|
+
const lineRange = {
|
|
16
|
+
end: lineEnd,
|
|
17
|
+
start: lineStart,
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
contents,
|
|
21
|
+
lineRange,
|
|
22
|
+
};
|
|
16
23
|
});
|
|
17
|
-
return linesWithTemplate;
|
|
18
24
|
}
|
|
19
25
|
export function ignoreErrors(file, lintErrors) {
|
|
20
|
-
const linesWithTemplate = findLinesWithTemplate(file);
|
|
21
26
|
const lines = file.split(EOL);
|
|
27
|
+
const templateTags = findTemplateTags(file);
|
|
22
28
|
lintErrors.forEach(({ line, message }) => {
|
|
23
|
-
const
|
|
24
|
-
|
|
29
|
+
const currentIndex = line - 1;
|
|
30
|
+
const previousIndex = Math.max(currentIndex - 1, 0);
|
|
31
|
+
const templateTagIndex = templateTags.findIndex(({ lineRange }) => {
|
|
32
|
+
return lineRange.start <= line && line <= lineRange.end;
|
|
33
|
+
});
|
|
34
|
+
const erroredInTemplate = templateTagIndex >= 0;
|
|
35
|
+
if (erroredInTemplate) {
|
|
36
|
+
const ignoreDirective = `{{! @glint-expect-error: ${message} }}`;
|
|
37
|
+
const { contents, lineRange } = templateTags[templateTagIndex];
|
|
38
|
+
if (lineRange.start !== lineRange.end) {
|
|
39
|
+
lines.splice(currentIndex, 0, ignoreDirective);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const newTemplate = lines[currentIndex].replace(/<template>(.+)<\/template>/, `<template>${ignoreDirective}${contents}</template>`);
|
|
43
|
+
lines.splice(currentIndex, 1, newTemplate);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const ignoreDirective = `// @ts-expect-error: ${message}`;
|
|
47
|
+
const ignoredRules = getIgnoredRules(lines[previousIndex], {
|
|
48
|
+
ignoreDirective: 'eslint-disable-next-line',
|
|
25
49
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
if (ignoredRules.length === 0) {
|
|
51
|
+
lines.splice(currentIndex, 0, ignoreDirective);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
lines.splice(previousIndex, 0, ignoreDirective);
|
|
55
|
+
}
|
|
30
56
|
});
|
|
31
57
|
return lines.join(EOL);
|
|
32
58
|
}
|
|
33
59
|
// For fallback, ignore type checks in templates
|
|
34
60
|
export function ignoreErrorsFallback(file, lintErrors) {
|
|
35
|
-
const linesWithTemplate = findLinesWithTemplate(file);
|
|
36
61
|
const lines = file.split(EOL);
|
|
62
|
+
const templateTags = findTemplateTags(file);
|
|
37
63
|
let hasErrorInTemplate = false;
|
|
38
64
|
lintErrors.forEach(({ line, message }) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
65
|
+
const currentIndex = line - 1;
|
|
66
|
+
const previousIndex = Math.max(currentIndex - 1, 0);
|
|
67
|
+
const erroredInTemplate = templateTags.some(({ lineRange }) => {
|
|
68
|
+
return lineRange.start <= line && line <= lineRange.end;
|
|
41
69
|
});
|
|
42
70
|
if (erroredInTemplate) {
|
|
43
71
|
hasErrorInTemplate = true;
|
|
44
72
|
return;
|
|
45
73
|
}
|
|
46
74
|
const ignoreDirective = `// @ts-expect-error: ${message}`;
|
|
47
|
-
|
|
75
|
+
const ignoredRules = getIgnoredRules(lines[previousIndex], {
|
|
76
|
+
ignoreDirective: 'eslint-disable-next-line',
|
|
77
|
+
});
|
|
78
|
+
if (ignoredRules.length === 0) {
|
|
79
|
+
lines.splice(currentIndex, 0, ignoreDirective);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
lines.splice(previousIndex, 0, ignoreDirective);
|
|
83
|
+
}
|
|
48
84
|
});
|
|
49
85
|
let newFile = lines.join(EOL);
|
|
50
86
|
if (hasErrorInTemplate) {
|
|
51
87
|
newFile = updateTemplates(newFile, (code) => {
|
|
52
88
|
const ignoreDirective = '{{! @glint-nocheck }}';
|
|
53
|
-
return [ignoreDirective, code].join(
|
|
89
|
+
return [ignoreDirective, code].join('');
|
|
54
90
|
});
|
|
55
91
|
}
|
|
56
92
|
return newFile;
|
|
@@ -60,8 +96,8 @@ export function isParseable(file) {
|
|
|
60
96
|
let isParseable = true;
|
|
61
97
|
try {
|
|
62
98
|
const templateTags = findTemplateTags(file);
|
|
63
|
-
templateTags.forEach((
|
|
64
|
-
traverse(
|
|
99
|
+
templateTags.forEach(({ contents }) => {
|
|
100
|
+
traverse(contents);
|
|
65
101
|
});
|
|
66
102
|
}
|
|
67
103
|
catch {
|
|
@@ -1,48 +1,31 @@
|
|
|
1
1
|
import { relative, sep } from 'node:path';
|
|
2
|
+
import { getFilesWithErrors } from './shared/index.js';
|
|
2
3
|
export const outputFilePath = '.ignore-lint-errors/eslint.txt';
|
|
3
|
-
|
|
4
|
+
function normalize(file, projectRoot) {
|
|
4
5
|
const filePathToData = new Map();
|
|
5
6
|
const records = JSON.parse(file);
|
|
6
7
|
records.forEach((record) => {
|
|
7
8
|
const { filePath: absoluteFilePath, messages } = record;
|
|
9
|
+
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
10
|
+
const lineToRules = new Map();
|
|
8
11
|
const data = new Map();
|
|
9
12
|
messages.forEach(({ line, ruleId }) => {
|
|
10
|
-
if (
|
|
11
|
-
|
|
13
|
+
if (lineToRules.has(line)) {
|
|
14
|
+
lineToRules.get(line).push(ruleId);
|
|
12
15
|
}
|
|
13
16
|
else {
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
18
|
-
filePathToData.set(filePath, data);
|
|
19
|
-
});
|
|
20
|
-
const filesWithErrors = [];
|
|
21
|
-
filePathToData.forEach((data, filePath) => {
|
|
22
|
-
const lintErrors = [];
|
|
23
|
-
data.forEach((allMessages, line) => {
|
|
24
|
-
const ruleIds = Array.from(new Set(allMessages.sort()));
|
|
25
|
-
lintErrors.push({
|
|
26
|
-
line,
|
|
27
|
-
message: ruleIds.join(', '),
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
if (lintErrors.length === 0) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
lintErrors.sort((a, b) => {
|
|
34
|
-
if (a.line < b.line) {
|
|
35
|
-
return 1;
|
|
36
|
-
}
|
|
37
|
-
if (b.line < a.line) {
|
|
38
|
-
return -1;
|
|
17
|
+
lineToRules.set(line, [ruleId]);
|
|
39
18
|
}
|
|
40
|
-
return 0;
|
|
41
19
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
lineToRules.forEach((rules, line) => {
|
|
21
|
+
const message = Array.from(new Set(rules.sort())).join(', ');
|
|
22
|
+
data.set(line, message);
|
|
45
23
|
});
|
|
24
|
+
filePathToData.set(filePath, data);
|
|
46
25
|
});
|
|
47
|
-
return
|
|
26
|
+
return filePathToData;
|
|
27
|
+
}
|
|
28
|
+
export function parseOutputFile(file, projectRoot) {
|
|
29
|
+
const filePathToData = normalize(file, projectRoot);
|
|
30
|
+
return getFilesWithErrors(filePathToData);
|
|
48
31
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function getFilesWithErrors(filePathToData) {
|
|
2
|
+
const filesWithErrors = [];
|
|
3
|
+
filePathToData.forEach((data, filePath) => {
|
|
4
|
+
const lintErrors = [];
|
|
5
|
+
data.forEach((message, line) => {
|
|
6
|
+
lintErrors.push({
|
|
7
|
+
line,
|
|
8
|
+
message,
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
if (lintErrors.length === 0) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
lintErrors.sort((a, b) => {
|
|
15
|
+
if (a.line < b.line) {
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
if (b.line < a.line) {
|
|
19
|
+
return -1;
|
|
20
|
+
}
|
|
21
|
+
return 0;
|
|
22
|
+
});
|
|
23
|
+
filesWithErrors.push({
|
|
24
|
+
filePath,
|
|
25
|
+
lintErrors,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
return filesWithErrors;
|
|
29
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { relative, sep } from 'node:path';
|
|
2
|
+
import { getFilesWithErrors } from './shared/index.js';
|
|
2
3
|
export const outputFilePath = '.ignore-lint-errors/stylelint.txt';
|
|
3
|
-
|
|
4
|
+
function normalize(file, projectRoot) {
|
|
4
5
|
const filePathToData = new Map();
|
|
5
6
|
const records = JSON.parse(file);
|
|
6
7
|
records.forEach((record) => {
|
|
@@ -8,44 +9,26 @@ export function parseOutputFile(file, projectRoot) {
|
|
|
8
9
|
if (!errored) {
|
|
9
10
|
return;
|
|
10
11
|
}
|
|
12
|
+
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
13
|
+
const lineToRules = new Map();
|
|
11
14
|
const data = new Map();
|
|
12
15
|
warnings.forEach(({ line, rule }) => {
|
|
13
|
-
if (
|
|
14
|
-
|
|
16
|
+
if (lineToRules.has(line)) {
|
|
17
|
+
lineToRules.get(line).push(rule);
|
|
15
18
|
}
|
|
16
19
|
else {
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
const filePath = relative(projectRoot, absoluteFilePath).replaceAll(sep, '/');
|
|
21
|
-
filePathToData.set(filePath, data);
|
|
22
|
-
});
|
|
23
|
-
const filesWithErrors = [];
|
|
24
|
-
filePathToData.forEach((data, filePath) => {
|
|
25
|
-
const lintErrors = [];
|
|
26
|
-
data.forEach((allMessages, line) => {
|
|
27
|
-
const ruleIds = Array.from(new Set(allMessages.sort()));
|
|
28
|
-
lintErrors.push({
|
|
29
|
-
line,
|
|
30
|
-
message: ruleIds.join(', '),
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
if (lintErrors.length === 0) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
lintErrors.sort((a, b) => {
|
|
37
|
-
if (a.line < b.line) {
|
|
38
|
-
return 1;
|
|
39
|
-
}
|
|
40
|
-
if (b.line < a.line) {
|
|
41
|
-
return -1;
|
|
20
|
+
lineToRules.set(line, [rule]);
|
|
42
21
|
}
|
|
43
|
-
return 0;
|
|
44
22
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
23
|
+
lineToRules.forEach((rules, line) => {
|
|
24
|
+
const message = Array.from(new Set(rules.sort())).join(', ');
|
|
25
|
+
data.set(line, message);
|
|
48
26
|
});
|
|
27
|
+
filePathToData.set(filePath, data);
|
|
49
28
|
});
|
|
50
|
-
return
|
|
29
|
+
return filePathToData;
|
|
30
|
+
}
|
|
31
|
+
export function parseOutputFile(file, projectRoot) {
|
|
32
|
+
const filePathToData = normalize(file, projectRoot);
|
|
33
|
+
return getFilesWithErrors(filePathToData);
|
|
51
34
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
|
+
import { getFilesWithErrors } from './shared/index.js';
|
|
2
3
|
export const outputFilePath = '.ignore-lint-errors/typescript.txt';
|
|
3
|
-
|
|
4
|
+
function normalize(file) {
|
|
4
5
|
const filePathToData = new Map();
|
|
5
6
|
file.split(EOL).forEach((str) => {
|
|
6
7
|
const matches = str.match(/^(.+)\((\d+),\d+\): error TS\d+: (.+)\.$/);
|
|
@@ -9,44 +10,17 @@ export function parseOutputFile(file) {
|
|
|
9
10
|
}
|
|
10
11
|
const filePath = matches[1];
|
|
11
12
|
const line = Number.parseInt(matches[2]);
|
|
12
|
-
const message =
|
|
13
|
+
const message = 'Incorrect type';
|
|
13
14
|
if (filePathToData.has(filePath)) {
|
|
14
|
-
|
|
15
|
-
filePathToData.get(filePath).get(line).push(message);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
filePathToData.get(filePath).set(line, [message]);
|
|
19
|
-
}
|
|
15
|
+
filePathToData.get(filePath).set(line, message);
|
|
20
16
|
}
|
|
21
17
|
else {
|
|
22
|
-
filePathToData.set(filePath, new Map([[line,
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
const filesWithErrors = [];
|
|
26
|
-
filePathToData.forEach((data, filePath) => {
|
|
27
|
-
const lintErrors = [];
|
|
28
|
-
data.forEach((_allMessages, line) => {
|
|
29
|
-
lintErrors.push({
|
|
30
|
-
line,
|
|
31
|
-
message: 'Incorrect type',
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
if (lintErrors.length === 0) {
|
|
35
|
-
return;
|
|
18
|
+
filePathToData.set(filePath, new Map([[line, message]]));
|
|
36
19
|
}
|
|
37
|
-
lintErrors.sort((a, b) => {
|
|
38
|
-
if (a.line < b.line) {
|
|
39
|
-
return 1;
|
|
40
|
-
}
|
|
41
|
-
if (b.line < a.line) {
|
|
42
|
-
return -1;
|
|
43
|
-
}
|
|
44
|
-
return 0;
|
|
45
|
-
});
|
|
46
|
-
filesWithErrors.push({
|
|
47
|
-
filePath,
|
|
48
|
-
lintErrors,
|
|
49
|
-
});
|
|
50
20
|
});
|
|
51
|
-
return
|
|
21
|
+
return filePathToData;
|
|
22
|
+
}
|
|
23
|
+
export function parseOutputFile(file) {
|
|
24
|
+
const filePathToData = normalize(file);
|
|
25
|
+
return getFilesWithErrors(filePathToData);
|
|
52
26
|
}
|