Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
3 changes: 1 addition & 2 deletions oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"tasks/e2e/**", // TODO
"napi/**", // TODO
"editors/vscode/tests/**", // TODO,
"tasks/lint_rules/src/oxlint-rules.mjs", // TODO
"tasks/lint_rules/src/main.mjs" // TODO

]
}
32 changes: 22 additions & 10 deletions tasks/lint_rules/src/main.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { parseArgs } from 'node:util';
import { ALL_TARGET_PLUGINS, createESLintLinter, loadTargetPluginRules } from './eslint-rules.mjs';
import { renderMarkdown } from './markdown-renderer.mjs';
import { updateGitHubIssue } from './result-reporter.mjs';
import {
ALL_TARGET_PLUGINS,
createESLintLinter,
loadTargetPluginRules,
} from './eslint-rules.mjs';
import {
createRuleEntries,
overrideTypeScriptPluginStatusWithEslintPluginStatus as syncTypeScriptPluginStatusWithEslintPluginStatus,
Expand All @@ -9,7 +14,6 @@ import {
updateImplementedStatus,
updateNotSupportedStatus,
} from './oxlint-rules.mjs';
import { updateGitHubIssue } from './result-reporter.mjs';

const HELP = `
Usage:
Expand All @@ -20,7 +24,7 @@ Options:
--update: Update the issue instead of printing to stdout
--help, -h: Print this help message

Plugins: ${Array.from(ALL_TARGET_PLUGINS.keys()).join(', ')}
Plugins: ${[...ALL_TARGET_PLUGINS.keys()].join(', ')}
`;

(async () => {
Expand All @@ -30,13 +34,15 @@ Plugins: ${Array.from(ALL_TARGET_PLUGINS.keys()).join(', ')}
const { values } = parseArgs({
options: {
// Mainly for debugging
target: { type: 'string', short: 't', multiple: true },
help: { short: 'h', type: 'boolean' },
target: { multiple: true, short: 't', type: 'string' },
update: { type: 'boolean' },
help: { type: 'boolean', short: 'h' },
},
});

if (values.help) return console.log(HELP);
if (values.help) {
return console.log(HELP);
}

const targetPluginNames = new Set(values.target ?? ALL_TARGET_PLUGINS.keys());
for (const pluginName of targetPluginNames) {
Expand Down Expand Up @@ -66,19 +72,25 @@ Plugins: ${Array.from(ALL_TARGET_PLUGINS.keys()).join(', ')}
// Render list and update if necessary
//
const results = await Promise.allSettled(
Array.from(targetPluginNames).map((pluginName) => {
[...targetPluginNames].map((pluginName) => {
const pluginMeta = /** @type {import("./eslint-rules.mjs").TargetPluginMeta} */ (
ALL_TARGET_PLUGINS.get(pluginName)
);
const content = renderMarkdown(pluginName, pluginMeta, ruleEntries);

if (!values.update) return Promise.resolve(content);
if (!values.update) {
return Promise.resolve(content);
}
// Requires `env.GITHUB_TOKEN`
return updateGitHubIssue(pluginMeta, content);
}),
);
for (const result of results) {
if (result.status === 'fulfilled') console.log(result.value);
if (result.status === 'rejected') console.error(result.reason);
if (result.status === 'fulfilled') {
console.log(result.value);
}
if (result.status === 'rejected') {
console.error(result.reason);
}
}
})();
67 changes: 38 additions & 29 deletions tasks/lint_rules/src/oxlint-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,26 @@ const readAllImplementedRuleNames = async () => {
line = line.trim();

// Skip commented out rules
if (line.startsWith('//')) continue;

if (line === 'oxc_macros::declare_all_lint_rules! {') {
found = true;
continue;
}
if (found && line === '}') {
return rules;
}

if (found) {
let prefixedName = line
.replaceAll(',', '')
.replaceAll('::', '/')
.replaceAll('_', '-');

// Ignore no reference rules
if (prefixedName.startsWith('oxc/')) continue;
if (prefixedName.startsWith('node/')) {
prefixedName = prefixedName.replace(/^node/, 'n');
if (!line.startsWith('//')) {
if (line === 'oxc_macros::declare_all_lint_rules! {') {
found = true;
} else if (found && line === '}') {
return rules;
} else if (found) {
let prefixedName = line
.replaceAll(',', '')
.replaceAll('::', '/')
.replaceAll('_', '-');

// Ignore no reference rules
if (!prefixedName.startsWith('oxc/')) {
if (prefixedName.startsWith('node/')) {
prefixedName = prefixedName.replace(/^node/, 'n');
}

rules.add(prefixedName);
}
}

rules.add(prefixedName);
}
}

Expand Down Expand Up @@ -243,7 +240,12 @@ export const createRuleEntries = (loadedAllRules) => {

for (const [name, rule] of loadedAllRules) {
// Default eslint rules are not prefixed
const prefixedName = name.includes('/') ? name : `eslint/${name}`;
let prefixedName = '';
if (name.includes('/')) {
prefixedName = name;
} else {
prefixedName = `eslint/${name}`;
}

const docsUrl = rule.meta?.docs?.url ?? '';
const isDeprecated = rule.meta?.deprecated ?? false;
Expand All @@ -252,10 +254,10 @@ export const createRuleEntries = (loadedAllRules) => {
rulesEntry.set(prefixedName, {
docsUrl,
isDeprecated: !!isDeprecated,
isRecommended,
// Will be updated later
isImplemented: false,
isNotSupported: false,
isRecommended,
});
}

Expand All @@ -268,16 +270,21 @@ export const updateImplementedStatus = async (ruleEntries) => {

for (const name of implementedRuleNames) {
const rule = ruleEntries.get(name);
if (rule) rule.isImplemented = true;
else console.log(`👀 ${name} is implemented but not found in their rules`);
if (rule) {
rule.isImplemented = true;
} else {
console.log(`👀 ${name} is implemented but not found in their rules`);
}
}
};

/** @param {RuleEntries} ruleEntries */
export const updateNotSupportedStatus = (ruleEntries) => {
for (const name of NOT_SUPPORTED_RULE_NAMES) {
const rule = ruleEntries.get(name);
if (rule) rule.isNotSupported = true;
if (rule) {
rule.isNotSupported = true;
}
}
};

Expand All @@ -296,7 +303,9 @@ const getArrayEntries = (constName, fileContent) => {
// ```
const regSearch = new RegExp(`const ${constName}[^=]+= \\[([^\\]]+)`, 's');

const vitestCompatibleRules = fileContent.match(regSearch)?.[1];
const FIRST_CAPTURE_GROUP = 1;
const matchResult = fileContent.match(regSearch);
const vitestCompatibleRules = matchResult?.[FIRST_CAPTURE_GROUP];
if (!vitestCompatibleRules) {
throw new Error('Failed to find the list of vitest-compatible rules');
}
Expand All @@ -310,7 +319,7 @@ const getArrayEntries = (constName, fileContent) => {
line
.replace(/"/g, '')
.split(',')
.filter((s) => s !== '')
.filter((str) => str !== '')
)
.flat(),
);
Expand Down
14 changes: 9 additions & 5 deletions tasks/lint_rules/src/result-reporter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ export const updateGitHubIssue = async ({ issueNo }, markdown) => {
const res = await fetch(
`https://api.github.com/repos/oxc-project/oxc/issues/${issueNo}`,
{
method: 'PATCH',
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
body: JSON.stringify({ body: markdown }),
headers: {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
},
body: JSON.stringify({ body: markdown }),
method: 'PATCH',
},
);
if (!res.ok) throw new Error(res.statusText);
} catch (err) {
throw new Error(`Failed to update issue: ${issueUrl}`, { cause: err });
if (!res.ok) {
throw new Error(res.statusText);
}
} catch (error) {
throw new Error(`Failed to update issue: ${issueUrl}`, { cause: error });
}

return `✅ ${issueUrl} is successfully updated`;
Expand Down