Last active
August 13, 2024 22:42
-
-
Save vsviridov/b70be92920e648583d7c841193b7c911 to your computer and use it in GitHub Desktop.
Effector ESLint Rule for suggesting `restore`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Rule } from 'eslint'; | |
import type ESTree from 'estree'; | |
export default { | |
'effector-restore': { | |
meta: { | |
docs: { | |
description: 'Replace simple store setting with restore', | |
category: 'Suggestions', | |
}, | |
fixable: 'code', | |
schema: [], | |
}, | |
create: (context) => { | |
const functionsReturningSecondArg: ESTree.ArrowFunctionExpression[] = []; | |
const createdStores: Record<string, ESTree.VariableDeclarator> = {}; | |
const createdEvents: Record<string, ESTree.VariableDeclarator> = {}; | |
const foundIssues: { | |
callExpr: ESTree.CallExpression; | |
eventName: string; | |
setter: ESTree.ArrowFunctionExpression; | |
}[] = []; | |
let effectorImport: ESTree.ImportDeclaration; | |
return { | |
['ImportDeclaration[source.value=effector]'](node: ESTree.ImportDeclaration) { | |
effectorImport = node; | |
}, | |
['CallExpression MemberExpression[property.name=on]'](node: Rule.Node) { | |
const callExpr = node.parent as ESTree.CallExpression; | |
const eventName = (callExpr.arguments[0] as ESTree.Identifier).name; | |
const setter = callExpr.arguments[1] as ESTree.ArrowFunctionExpression; | |
foundIssues.push({ callExpr, eventName, setter }); | |
}, | |
['VariableDeclarator CallExpression[callee.name=createStore][arguments.length=1]'](node: Rule.Node) { | |
switch (node.parent.type) { | |
case 'VariableDeclarator': { | |
createdStores[(node.parent.id as ESTree.Identifier).name] = node.parent as ESTree.VariableDeclarator; | |
} | |
} | |
}, | |
['VariableDeclarator CallExpression[callee.name=createEvent]'](node: Rule.Node) { | |
switch (node.parent.type) { | |
case 'VariableDeclarator': { | |
createdEvents[(node.parent.id as ESTree.Identifier).name] = node.parent; | |
} | |
} | |
}, | |
['ArrowFunctionExpression[body.type=Identifier][params.length=2]'](node: ESTree.ArrowFunctionExpression) { | |
if ((node.body as ESTree.Identifier).name === (node.params[1] as ESTree.Identifier).name) { | |
functionsReturningSecondArg.push(node); | |
} | |
}, | |
['Program:exit'](_node) { | |
foundIssues.forEach(({ callExpr, eventName, setter }) => { | |
if (functionsReturningSecondArg.includes(setter)) { | |
const storeName = ((callExpr.callee as ESTree.MemberExpression).object as ESTree.Identifier).name; | |
const store = createdStores[storeName]; | |
if (!store) { | |
return; | |
} | |
// const event = createdEvents[eventName]; | |
// if(!event) { return; } | |
// const eventRaw = context.sourceCode.getText(event.parent); | |
context.report({ | |
node: setter, | |
message: `This can be replaced with "restore"`, | |
// fix: (fixer) => { | |
// return [ | |
// // fixer.remove(event.parent), | |
// fixer.insertTextAfter(effectorImport.specifiers[effectorImport.specifiers.length - 1], ', restore'), | |
// fixer.replaceText( | |
// store, | |
// `${storeName} = restore(${eventName}, ${ | |
// ((store.init as ESTree.CallExpression).arguments[0] as ESTree.Literal).raw | |
// })` | |
// ), | |
// fixer.remove((callExpr as Rule.Node).parent), | |
// ]; | |
// }, | |
}); | |
} | |
}); | |
}, | |
} satisfies Rule.RuleListener; | |
}, | |
}, | |
} satisfies Record<string, Rule.RuleModule>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment