Skip to content

Commit

Permalink
[Refactor] add getMessageData util
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Nov 21, 2022
1 parent cc9578c commit 01ab399
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 35 deletions.
75 changes: 43 additions & 32 deletions lib/rules/hook-use-state.js
Expand Up @@ -8,6 +8,7 @@
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');
const report = require('../util/report');
const getMessageData = require('../util/message');

// ------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -20,6 +21,8 @@ function isNodeDestructuring(node) {
const messages = {
useStateErrorMessage: 'useState call is not destructured into value + setter pair',
useStateErrorMessageOrAddOption: 'useState call is not destructured into value + setter pair (you can allow destructuring by enabling "allowDestructuredState" option)',
suggestPair: 'Destructure useState call into value + setter pair',
suggestMemo: 'Replace useState call with useMemo',
};

module.exports = {
Expand Down Expand Up @@ -67,7 +70,10 @@ module.exports = {
context,
messages.useStateErrorMessage,
'useStateErrorMessage',
{ node }
{
node,
suggest: false,
}
);
return;
}
Expand Down Expand Up @@ -104,21 +110,23 @@ module.exports = {

if (!isSymmetricGetterSetterPair) {
const suggestions = [
{
desc: 'Destructure useState call into value + setter pair',
fix: (fixer) => {
if (expectedSetterVariableNames.length === 0) {
return;
}

const fix = fixer.replaceTextRange(
node.parent.id.range,
`[${valueVariableName}, ${expectedSetterVariableNames[0]}]`
);

return fix;
},
},
Object.assign(
getMessageData('suggestPair', messages.suggestPair),
{
fix(fixer) {
if (expectedSetterVariableNames.length === 0) {
return;
}

const fix = fixer.replaceTextRange(
node.parent.id.range,
`[${valueVariableName}, ${expectedSetterVariableNames[0]}]`
);

return fix;
},
}
),
];

const defaultReactImports = components.getDefaultReactImports();
Expand Down Expand Up @@ -150,22 +158,24 @@ module.exports = {
useMemoCode = 'useMemo';
}

suggestions.unshift({
desc: 'Replace useState call with useMemo',
fix: (fixer) => [
// Add useMemo import, if necessary
useStateReactImportSpecifier
&& (!useMemoReactImportSpecifier || defaultReactImportName)
&& fixer.insertTextAfter(useStateReactImportSpecifier, ', useMemo'),
// Convert single-value destructure to simple assignment
fixer.replaceTextRange(node.parent.id.range, valueVariableName),
// Convert useState call to useMemo + arrow function + dependency array
fixer.replaceTextRange(
node.range,
`${useMemoCode}(() => ${context.getSourceCode().getText(node.arguments[0])}, [])`
),
].filter(Boolean),
});
suggestions.unshift(Object.assign(
getMessageData('suggestMemo', messages.suggestMemo),
{
fix: (fixer) => [
// Add useMemo import, if necessary
useStateReactImportSpecifier
&& (!useMemoReactImportSpecifier || defaultReactImportName)
&& fixer.insertTextAfter(useStateReactImportSpecifier, ', useMemo'),
// Convert single-value destructure to simple assignment
fixer.replaceTextRange(node.parent.id.range, valueVariableName),
// Convert useState call to useMemo + arrow function + dependency array
fixer.replaceTextRange(
node.range,
`${useMemoCode}(() => ${context.getSourceCode().getText(node.arguments[0])}, [])`
),
].filter(Boolean),
}
));
}

if (isOnlyValueDestructuring) {
Expand All @@ -175,6 +185,7 @@ module.exports = {
'useStateErrorMessageOrAddOption',
{
node: node.parent.id,
suggest: false,
}
);
return;
Expand Down
8 changes: 8 additions & 0 deletions lib/util/message.js
@@ -0,0 +1,8 @@
'use strict';

const semver = require('semver');
const eslintPkg = require('eslint/package.json');

module.exports = function getMessageData(messageId, message) {
return messageId && semver.satisfies(eslintPkg.version, '>= 4.15') ? { messageId } : { message };
};
5 changes: 2 additions & 3 deletions lib/util/report.js
@@ -1,12 +1,11 @@
'use strict';

const semver = require('semver');
const eslintPkg = require('eslint/package.json');
const getMessageData = require('./message');

module.exports = function report(context, message, messageId, data) {
context.report(
Object.assign(
messageId && semver.satisfies(eslintPkg.version, '>= 4.15') ? { messageId } : { message },
getMessageData(messageId, message),
data
)
);
Expand Down

0 comments on commit 01ab399

Please sign in to comment.