-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathlint.ts
More file actions
73 lines (68 loc) · 2.08 KB
/
lint.ts
File metadata and controls
73 lines (68 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import type { ESLint, Linter } from 'eslint';
import { distinct, executeProcess, toArray } from '@code-pushup/utils';
import type { ESLintTarget } from '../config.js';
import { setupESLint } from '../setup.js';
import type { LinterOutput, RuleOptionsPerFile } from './types.js';
export async function lint({
eslintrc,
patterns,
}: ESLintTarget): Promise<LinterOutput> {
const results = await executeLint({ eslintrc, patterns });
const eslint = await setupESLint(eslintrc);
const ruleOptionsPerFile = await loadRuleOptionsPerFile(eslint, results);
return { results, ruleOptionsPerFile };
}
async function executeLint({
eslintrc,
patterns,
}: ESLintTarget): Promise<ESLint.LintResult[]> {
// running as CLI because ESLint#lintFiles() runs out of memory
const { stdout, stderr, code } = await executeProcess({
command: 'npx',
args: [
'eslint',
...(eslintrc ? [`--config=${eslintrc}`] : []),
...(typeof eslintrc === 'object' ? ['--no-eslintrc'] : []),
'--no-error-on-unmatched-pattern',
'--format=json',
...toArray(patterns),
],
ignoreExitCode: true,
cwd: process.cwd(),
});
if (!stdout.trim()) {
throw new Error(
`ESLint produced empty output. Exit code: ${code}, STDERR: ${stderr}`,
);
}
return JSON.parse(stdout) as ESLint.LintResult[];
}
function loadRuleOptionsPerFile(
eslint: ESLint,
results: ESLint.LintResult[],
): Promise<RuleOptionsPerFile> {
return results.reduce(async (acc, { filePath, messages }) => {
const filesMap = await acc;
const config = (await eslint.calculateConfigForFile(
filePath,
)) as Linter.Config;
const ruleIds = distinct(
messages
.map(({ ruleId }) => ruleId)
.filter((ruleId): ruleId is string => ruleId != null),
);
const rulesMap = Object.fromEntries(
ruleIds.map(ruleId => [
ruleId,
toArray(config.rules?.[ruleId] ?? []).slice(1),
]),
);
return {
...filesMap,
[filePath]: {
...filesMap[filePath],
...rulesMap,
},
};
}, Promise.resolve<RuleOptionsPerFile>({}));
}