Skip to content

Commit f3c28a8

Browse files
committed
chore: add oxlint, bump ESLint to v10
1 parent 9cfb678 commit f3c28a8

File tree

14 files changed

+757
-1334
lines changed

14 files changed

+757
-1334
lines changed

.oxlintrc.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "./node_modules/oxlint/configuration_schema.json",
3+
"plugins": ["eslint", "oxc", "typescript", "import", "jsdoc"],
4+
"ignorePatterns": [
5+
"**/coverage/",
6+
"**/dist/",
7+
"**/types/",
8+
"**/build/",
9+
"**/static/",
10+
"**/*.d.ts"
11+
],
12+
"categories": {
13+
"correctness": "error",
14+
"suspicious": "error"
15+
},
16+
"rules": {
17+
"no-console": ["error", { "allow": ["warn", "error"] }],
18+
"typescript/no-unsafe-type-assertion": "off",
19+
"typescript/require-await": "error"
20+
}
21+
}

dist/cjs/index.cjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
var _package = require('./package.json.cjs');
4+
var noUnusedDeps = require('./rules/no-unused-deps.cjs');
5+
6+
const rules = {
7+
'react-hooks-addons/no-unused-deps': 'error'
8+
};
9+
const plugin = {
10+
meta: {
11+
name: _package.name,
12+
version: _package.version
13+
},
14+
configs: {
15+
recommended: {},
16+
'recommended-legacy': {}
17+
},
18+
rules: {
19+
'no-unused-deps': noUnusedDeps
20+
}
21+
};
22+
plugin.configs.recommended = {
23+
plugins: {
24+
'react-hooks-addons': plugin
25+
},
26+
rules
27+
};
28+
plugin.configs['recommended-legacy'] = {
29+
plugins: ['react-hooks-addons'],
30+
rules
31+
};
32+
33+
module.exports = plugin;

dist/cjs/package.json.cjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
var _package = {
4+
name: "eslint-plugin-react-hooks-addons",
5+
version: "0.5.0"};
6+
7+
module.exports = _package;

dist/cjs/rules/no-unused-deps.cjs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'use strict';
2+
3+
/**
4+
* Rule to check unused dependencies in React Hooks
5+
* @author Zheng Song
6+
*/
7+
8+
const reactNamespace = 'React';
9+
const hookNames = ['useEffect', 'useLayoutEffect'];
10+
const matchHooks = (name, {
11+
pattern,
12+
replace
13+
} = {}) => {
14+
let match = false;
15+
if (pattern) {
16+
match = new RegExp(pattern).test(name);
17+
if (replace) return match;
18+
}
19+
return match || hookNames.includes(name);
20+
};
21+
const rule = {
22+
meta: {
23+
type: 'problem',
24+
schema: [{
25+
type: 'object',
26+
properties: {
27+
effectComment: {
28+
type: 'string'
29+
},
30+
additionalHooks: {
31+
type: 'object',
32+
properties: {
33+
pattern: {
34+
type: 'string'
35+
},
36+
replace: {
37+
type: 'boolean'
38+
}
39+
},
40+
required: ['pattern'],
41+
additionalProperties: false
42+
}
43+
},
44+
additionalProperties: false
45+
}],
46+
messages: {
47+
unused: 'React Hook {{ hook }} has unused dependencies: {{ unusedDeps }}. They might cause the Hook to run unintentionally. Either exclude them or prepend /* {{ effectComment }} */ comments to make the intention explicit.'
48+
}
49+
},
50+
create(context) {
51+
var _context$sourceCode;
52+
const {
53+
effectComment = 'effect dep',
54+
additionalHooks
55+
} = context.options[0] || {};
56+
const sourceCode = (_context$sourceCode = context.sourceCode) != null ? _context$sourceCode : context.getSourceCode();
57+
const nodeListener = node => {
58+
const {
59+
parent
60+
} = node;
61+
if (parent.type !== 'CallExpression' || parent.arguments.length < 2 || parent.arguments[1].type !== 'ArrayExpression') {
62+
return;
63+
}
64+
const {
65+
callee
66+
} = parent;
67+
let hookName;
68+
switch (callee.type) {
69+
case 'Identifier':
70+
hookName = callee.name;
71+
break;
72+
case 'MemberExpression':
73+
if (callee.object.type === 'Identifier' && callee.object.name === reactNamespace && callee.property.type === 'Identifier') {
74+
hookName = callee.property.name;
75+
}
76+
break;
77+
}
78+
if (!hookName || !matchHooks(hookName, additionalHooks)) return;
79+
const scope = sourceCode.getScope ? sourceCode.getScope(node) : context.getScope();
80+
const through = scope.through.map(r => r.identifier.name);
81+
const depArray = parent.arguments[1];
82+
const deps = depArray.elements.filter(e => (e == null ? void 0 : e.type) === 'Identifier');
83+
const unusedDeps = [];
84+
for (const dep of deps) {
85+
if (through.includes(dep.name)) continue;
86+
if (sourceCode.getCommentsBefore(dep).some(({
87+
value
88+
}) => value.includes(effectComment))) {
89+
continue;
90+
}
91+
unusedDeps.push(dep.name);
92+
}
93+
if (unusedDeps.length > 0) {
94+
context.report({
95+
node: depArray,
96+
messageId: 'unused',
97+
data: {
98+
hook: hookName,
99+
unusedDeps: unusedDeps.map(dep => `'${dep}'`).join(', '),
100+
effectComment
101+
}
102+
});
103+
}
104+
};
105+
return {
106+
'ArrowFunctionExpression,FunctionExpression': nodeListener
107+
};
108+
}
109+
};
110+
111+
module.exports = rule;

eslint.config.mjs

Lines changed: 0 additions & 27 deletions
This file was deleted.

examples/.oxlintrc.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "./node_modules/oxlint/configuration_schema.json",
3+
"plugins": ["eslint", "oxc", "import", "jsdoc", "vitest", "react"],
4+
"jsPlugins": ["eslint-plugin-react-hooks-addons"],
5+
"categories": {
6+
"correctness": "error",
7+
"suspicious": "error"
8+
},
9+
"rules": {
10+
"react/react-in-jsx-scope": "off",
11+
"react-hooks/rules-of-hooks": "error",
12+
"react-hooks/exhaustive-deps": "error",
13+
"react-hooks-addons/no-unused-deps": "error"
14+
}
15+
}

examples/eslint.config.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import eslint from '@eslint/js';
44
import globals from 'globals';
55
import prettier from 'eslint-config-prettier';
6-
import reactHooks from 'eslint-plugin-react-hooks';
6+
// import reactHooks from 'eslint-plugin-react-hooks';
77
import reactHooksAddons from 'eslint-plugin-react-hooks-addons';
88

99
/**
1010
* @type {import('eslint').Linter.Config[]}
1111
*/
1212
export default [
1313
eslint.configs.recommended,
14-
reactHooks.configs.flat.recommended,
14+
// reactHooks.configs.flat.recommended,
1515
reactHooksAddons.configs.recommended,
1616
prettier,
1717
{
@@ -20,11 +20,11 @@ export default [
2020
globals: {
2121
...globals.browser
2222
}
23-
},
24-
rules: {
25-
'react-hooks/rules-of-hooks': 'error',
26-
'react-hooks/exhaustive-deps': 'error',
27-
'react-hooks/set-state-in-effect': 'off'
2823
}
24+
// rules: {
25+
// 'react-hooks/rules-of-hooks': 'error',
26+
// 'react-hooks/exhaustive-deps': 'error',
27+
// 'react-hooks/set-state-in-effect': 'off'
28+
// }
2929
}
3030
];

0 commit comments

Comments
 (0)