blob: 7797a714f58827352a53755fb324f79e8b3e8a34 [file]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {ESLint} from 'eslint';
import {join} from 'node:path';
export async function runESLint(scriptFiles, {fix, lintOnly, forceFix, debug}) {
if (scriptFiles.length === 0) {
return {status: true, output: ''};
}
const linterFixer = fix && !lintOnly;
const cacheLinters = !debug && !lintOnly;
const messages = [];
if (debug) {
messages.push('[lint]: Running EsLint...');
}
const cli = new ESLint({
cwd: join(import.meta.dirname, '..', '..'),
fix: linterFixer,
cache: cacheLinters,
allowInlineConfig: !forceFix,
});
// We filter out certain files in the `eslint.config.mjs` `Ignore list` entry.
// However, ESLint produces warnings
// when you include a particular file that is ignored. This means that if you edit a file
// that is directly ignored. ESLint would report a failure.
// This was originally reported in https://github.com/eslint/eslint/issues/9977
// The suggested workaround is to use the CLIEngine to preemptively filter out these
// problematic paths.
const files = (
await Promise.all(
scriptFiles.map(async file => {
return (await cli.isPathIgnored(file)) ? null : file;
}),
)
).filter(file => file !== null);
if (files.length === 0) {
// When an empty array is pass lint CWD
// This can happen only if we pass things that will
// be ignored by the above filter
// https://github.com/eslint/eslint/pull/17644
return {status: true, output: messages.join('\n')};
}
const results = await cli.lintFiles(files);
const usedDeprecatedRules = results.flatMap(
result => result.usedDeprecatedRules,
);
if (usedDeprecatedRules.length) {
messages.push('Used deprecated rules:');
for (const {ruleId, replacedBy} of usedDeprecatedRules) {
messages.push(
` Rule ${ruleId} can be replaced with ${replacedBy?.join(',') ?? 'none'}`,
);
}
}
if (files.length === 1 && debug) {
messages.push('[lint]: EsLint suppressed the following errors:');
for (const result of results) {
for (const message of result.suppressedMessages) {
messages.push(JSON.stringify(message));
}
}
}
if (linterFixer) {
await ESLint.outputFixes(results);
}
const formatter = await cli.loadFormatter('stylish');
const output = formatter.format(results);
if (output) {
messages.push(output);
}
return {
status: !results.find(
report => report.errorCount + report.warningCount > 0,
),
output: messages.join('\n'),
};
}