|
#!/usr/bin/env node |
|
import { createESLintLinter, loadTargetPluginRules } from "./eslint-rules.mjs"; |
|
import { |
|
createRuleEntries, |
|
updateImplementedStatus, |
|
updateNotSupportedStatus, |
|
updatePendingFixStatus, |
|
overrideTypeScriptPluginStatusWithEslintPluginStatus, |
|
syncVitestPluginStatusWithJestPluginStatus, |
|
syncUnicornPluginStatusWithEslintPluginStatus, |
|
} from "./oxlint-rules.mjs"; |
|
|
|
const main = async () => { |
|
const linter = createESLintLinter(); |
|
loadTargetPluginRules(linter); |
|
|
|
const ruleEntries = createRuleEntries(linter.getRules()); |
|
|
|
await updateImplementedStatus(ruleEntries); |
|
updateNotSupportedStatus(ruleEntries); |
|
await updatePendingFixStatus(ruleEntries); |
|
|
|
// Sync / override statuses across plugins so counts are more accurate |
|
await overrideTypeScriptPluginStatusWithEslintPluginStatus(ruleEntries); |
|
await syncVitestPluginStatusWithJestPluginStatus(ruleEntries); |
|
syncUnicornPluginStatusWithEslintPluginStatus(ruleEntries); |
|
|
|
// Group by plugin prefix (before '/') |
|
const byPlugin = new Map(); |
|
|
|
for (const [name, entry] of ruleEntries) { |
|
const [plugin] = name.split("/"); |
|
const stats = byPlugin.get(plugin) ?? { total: 0, implemented: 0, notSupported: 0, pending: 0, deprecated: 0 }; |
|
// TODO: Maybe don't count deprecated in the total? Not sure. |
|
stats.total += 1; |
|
if (entry.isDeprecated) stats.deprecated += 1; |
|
if (entry.isImplemented) stats.implemented += 1; |
|
if (entry.isNotSupported) stats.notSupported += 1; |
|
if (entry.isPendingFix) stats.pending += 1; |
|
byPlugin.set(plugin, stats); |
|
} |
|
|
|
// Sort plugins alphabetically, but keep 'eslint' and 'typescript' at the top for readability |
|
const plugins = Array.from(byPlugin.keys()).sort((a, b) => { |
|
if (a === "eslint") return -1; |
|
if (b === "eslint") return 1; |
|
if (a === "typescript") return -1; |
|
if (b === "typescript") return 1; |
|
return a.localeCompare(b); |
|
}); |
|
|
|
// Print markdown table header |
|
console.log("| Plugin | Total | Implemented | Supported % | Not supported | Pending fix | Still need to implement |"); |
|
console.log("|---|---:|---:|---:|---:|---:|---:|"); |
|
|
|
let totalAll = 0; |
|
let totalImplemented = 0; |
|
let totalNotSupported = 0; |
|
let totalPending = 0; |
|
let totalDeprecated = 0; |
|
|
|
for (const plugin of plugins) { |
|
const { total, implemented, notSupported, pending, deprecated } = byPlugin.get(plugin); |
|
const stillNeed = total - implemented - notSupported; |
|
const actionableTotal = total - notSupported; // rules that actually need implementation |
|
const pct = actionableTotal <= 0 ? 100 : (implemented / actionableTotal) * 100; |
|
// Format percent with at most 1 decimal, only show decimal if needed |
|
const pctStr = (() => { |
|
const fixed = Math.round(pct * 10) / 10; // ensures one decimal precision rounded |
|
if (Number.isInteger(fixed)) return `${fixed}%`; |
|
return `${fixed.toFixed(1)}%`; |
|
})(); |
|
|
|
totalAll += total; |
|
totalImplemented += implemented; |
|
totalNotSupported += notSupported; |
|
totalPending += pending; |
|
totalDeprecated += deprecated; |
|
|
|
console.log(`| ${plugin} | ${total} | ${implemented} | ${pctStr} | ${notSupported} | ${pending} | ${stillNeed} |`); |
|
} |
|
|
|
const stillNeedAll = totalAll - totalImplemented - totalNotSupported; |
|
|
|
console.log(); |
|
const actionableTotalAll = totalAll - totalNotSupported; |
|
const overallPct = actionableTotalAll <= 0 ? 100 : (totalImplemented / actionableTotalAll) * 100; |
|
const overallPctStr = (() => { |
|
const fixed = Math.round(overallPct * 10) / 10; |
|
return Number.isInteger(fixed) ? `${fixed}%` : `${fixed.toFixed(1)}%`; |
|
})(); |
|
|
|
console.log(`Supported rules: ${totalImplemented} (${overallPctStr}), No need to implement: ${totalNotSupported}, Deprecated: ${totalDeprecated}, Still need to implement: ${stillNeedAll}, total: ${totalImplemented} supported/${totalImplemented + stillNeedAll} rules`); |
|
console.log(); |
|
console.log(`(All rules counted: ${totalAll} total, with ${totalPending} marked implemented but pending fixes)`); |
|
}; |
|
|
|
main().catch((e) => { |
|
// eslint-disable-next-line no-console |
|
console.error(e); |
|
process.exit(1); |
|
}); |