Upgrade to ESLint 9

This commit is contained in:
Alex
2024-10-16 00:29:26 -04:00
parent 0138cabb27
commit 00d0dfa107
53 changed files with 3813 additions and 2207 deletions

View File

@ -6,7 +6,6 @@
*/
/* global BigInt */
/* eslint-disable no-for-of-loops/no-for-of-loops */
import type { Rule, Scope } from 'eslint';
import type {
CallExpression,
@ -16,6 +15,7 @@ import type {
Identifier,
BaseFunction,
} from 'estree';
import { __EXPERIMENTAL__ } from './index';
/**
@ -24,10 +24,7 @@ import { __EXPERIMENTAL__ } from './index';
*/
function isHookName(s: string) {
if (__EXPERIMENTAL__) {
return s === 'use' || /^use[A-Z0-9]/.test(s);
}
return /^use[A-Z0-9]/.test(s);
return s === 'use' || /^use[\dA-Z]/.test(s);
}
/**
@ -94,10 +91,8 @@ function isMemoCallback(node: Rule.Node) {
function isInsideComponentOrHook(node: Rule.Node) {
while (node) {
const functionName = getFunctionName(node);
if (functionName) {
if (isComponentName(functionName) || isHook(functionName)) {
return true;
}
if (functionName && (isComponentName(functionName) || isHook(functionName))) {
return true;
}
if (isForwardRefCallback(node) || isMemoCallback(node)) {
return true;
@ -115,10 +110,7 @@ function isUseEffectEventIdentifier(node: Node) {
}
function isUseIdentifier(node: Node) {
if (__EXPERIMENTAL__) {
return node.type === 'Identifier' && node.name === 'use';
}
return false;
return isReactFunction(node as Expression, 'use');
}
const rule: Rule.RuleModule = {
@ -161,6 +153,22 @@ const rule: Rule.RuleModule = {
}
}
/**
* SourceCode#getText that also works down to ESLint 3.0.0
*/
const getSource =
typeof context.getSource === 'function'
? (node: Node) => context.getSource(node)
: (node: Node) => context.sourceCode.getText(node);
/**
* SourceCode#getScope that also works down to ESLint 3.0.0
*/
const getScope =
typeof context.getScope === 'function'
? () => context.getScope()
: (node: Node) => context.sourceCode.getScope(node);
return {
// Maintain code segment path stack as we traverse.
onCodePathSegmentStart: segment => codePathSegmentStack.push(segment),
@ -479,7 +487,7 @@ const rule: Rule.RuleModule = {
context.report({
node: hook,
message:
`React Hook "${context.getSource(hook)}" may be executed ` +
`React Hook "${getSource(hook)}" may be executed ` +
'more than once. Possibly because it is called in a loop. ' +
'React Hooks must be called in the exact same order in ' +
'every component render.',
@ -498,7 +506,7 @@ const rule: Rule.RuleModule = {
context.report({
node: hook,
message:
`React Hook "${context.getSource(hook)}" cannot be ` +
`React Hook "${getSource(hook)}" cannot be ` +
'called in an async function.',
});
}
@ -513,7 +521,7 @@ const rule: Rule.RuleModule = {
!isUseIdentifier(hook) // `use(...)` can be called conditionally.
) {
const message =
`React Hook "${context.getSource(hook)}" is called ` +
`React Hook "${getSource(hook)}" is called ` +
'conditionally. React Hooks must be called in the exact ' +
'same order in every component render.' +
(possiblyHasEarlyReturn
@ -530,15 +538,15 @@ const rule: Rule.RuleModule = {
) {
// Custom message for hooks inside a class
const message =
`React Hook "${context.getSource(hook)}" cannot be called ` +
`React Hook "${getSource(hook)}" cannot be called ` +
'in a class component. React Hooks must be called in a ' +
'React function component or a custom React Hook function.';
context.report({ node: hook, message });
} else if (codePathFunctionName) {
// Custom message if we found an invalid function name.
const message =
`React Hook "${context.getSource(hook)}" is called in ` +
`function "${context.getSource(codePathFunctionName)}" ` +
`React Hook "${getSource(hook)}" is called in ` +
`function "${getSource(codePathFunctionName)}" ` +
'that is neither a React function component nor a custom ' +
'React Hook function.' +
' React component names must start with an uppercase letter.' +
@ -547,7 +555,7 @@ const rule: Rule.RuleModule = {
} else if (codePathNode.type === 'Program') {
// These are dangerous if you have inline requires enabled.
const message =
`React Hook "${context.getSource(hook)}" cannot be called ` +
`React Hook "${getSource(hook)}" cannot be called ` +
'at the top level. React Hooks must be called in a ' +
'React function component or a custom React Hook function.';
context.report({ node: hook, message });
@ -560,7 +568,7 @@ const rule: Rule.RuleModule = {
// `use(...)` can be called in callbacks.
if (isSomewhereInsideComponentOrHook && !isUseIdentifier(hook)) {
const message =
`React Hook "${context.getSource(hook)}" cannot be called ` +
`React Hook "${getSource(hook)}" cannot be called ` +
'inside a callback. React Hooks must be called in a ' +
'React function component or a custom React Hook function.';
context.report({ node: hook, message });
@ -612,7 +620,7 @@ const rule: Rule.RuleModule = {
context.report({
node,
message:
`\`${context.getSource(
`\`${getSource(
node,
)}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
'the same component. They cannot be assigned to variables or passed down.',
@ -629,14 +637,14 @@ const rule: Rule.RuleModule = {
FunctionDeclaration(node) {
// function MyComponent() { const onClick = useEffectEvent(...) }
if (isInsideComponentOrHook(node)) {
recordAllUseEffectEventFunctions(context.getScope());
recordAllUseEffectEventFunctions(getScope(node));
}
},
ArrowFunctionExpression(node) {
// const MyComponent = () => { const onClick = useEffectEvent(...) }
if (isInsideComponentOrHook(node)) {
recordAllUseEffectEventFunctions(context.getScope());
recordAllUseEffectEventFunctions(getScope(node));
}
},
};