diff --git a/rules/enforce-store-naming-convention/enforce-store-naming-convention.js b/rules/enforce-store-naming-convention/enforce-store-naming-convention.js index 8139939..b2d18b8 100644 --- a/rules/enforce-store-naming-convention/enforce-store-naming-convention.js +++ b/rules/enforce-store-naming-convention/enforce-store-naming-convention.js @@ -14,6 +14,11 @@ const { const { createLinkToRule } = require("../../utils/create-link-to-rule"); const { nodeTypeIs } = require("../../utils/node-type-is"); const { traverseParentByType } = require("../../utils/traverse-parent-by-type"); +const { + traverseRealDeclaration, +} = require("../../utils/traverse-real-declaration"); +const { nodeName } = require("../../utils/node-name"); +const { nodeRange } = require("../../utils/node-range"); module.exports = { meta: { @@ -47,23 +52,27 @@ module.exports = { if (parserServices?.program) { return { VariableDeclarator(node) { - const isEffectorStore = nodeTypeIs.store({ - node, - context, - }); - - if (!isEffectorStore) { - return; - } - - const storeName = node.id.name; + const realNodes = traverseRealDeclaration(node); - if (namingOf.store.isInvalid({ name: storeName, context })) { - reportStoreNameConventionViolation({ + for (const realNode of realNodes) { + const isEffectorStore = nodeTypeIs.store({ + node: realNode, context, - node, - storeName, }); + + if (!isEffectorStore) { + continue; + } + + const storeName = nodeName(realNode); + + if (namingOf.store.isInvalid({ name: storeName, context })) { + reportStoreNameConventionViolation({ + context, + node: realNode, + storeName, + }); + } } }, }; @@ -197,7 +206,7 @@ function reportStoreNameConventionViolation({ context, node, storeName }) { messageId: "renameStore", data: { storeName, correctedStoreName }, fix(fixer) { - return fixer.replaceTextRange(node.id.range, correctedStoreName); + return fixer.replaceTextRange(nodeRange(node), correctedStoreName); }, }, ], diff --git a/rules/enforce-store-naming-convention/prefix/enforce-store-naming-convention-prefix.ts.test.js b/rules/enforce-store-naming-convention/prefix/enforce-store-naming-convention-prefix.ts.test.js index ababaf4..ee17b22 100644 --- a/rules/enforce-store-naming-convention/prefix/enforce-store-naming-convention-prefix.ts.test.js +++ b/rules/enforce-store-naming-convention/prefix/enforce-store-naming-convention-prefix.ts.test.js @@ -18,33 +18,46 @@ const readExampleForTheRule = (name) => ({ filename: join(__dirname, "examples", name), }); -ruleTester.run( - "enforce-store-naming-convention-prefix.ts.test", - rule, - { - valid: ["correct-store-naming.ts", "correct-issue-139.ts"].map( - readExampleForTheRule - ), +ruleTester.run("enforce-store-naming-convention-prefix.ts.test", rule, { + valid: ["correct-store-naming.ts", "correct-issue-139.ts"].map( + readExampleForTheRule + ), - invalid: [ - // Errors - ...["incorrect-store-naming.ts"] - .map(readExampleForTheRule) - .map((result) => ({ - ...result, - errors: [ - { - messageId: "invalidName", - type: "VariableDeclarator", - suggestions: [ - { - messageId: "renameStore", - output: result.code.replace("justStore", "$justStore"), - }, - ], - }, - ], - })), - ], - } -); + invalid: [ + // Errors + ...["incorrect-store-naming.ts"] + .map(readExampleForTheRule) + .map((result) => ({ + ...result, + errors: [ + { + messageId: "invalidName", + type: "VariableDeclarator", + suggestions: [ + { + messageId: "renameStore", + output: result.code.replace("justStore", "$justStore"), + }, + ], + }, + ], + })), + ...["incorrect-store-after-destruction.ts"] + .map(readExampleForTheRule) + .map((result) => ({ + ...result, + errors: [ + { + messageId: "invalidName", + type: "Identifier", + suggestions: [ + { + messageId: "renameStore", + output: result.code.replace("justStore", "$justStore"), + }, + ], + }, + ], + })), + ], +}); diff --git a/rules/enforce-store-naming-convention/prefix/examples/incorrect-store-after-destruction.ts b/rules/enforce-store-naming-convention/prefix/examples/incorrect-store-after-destruction.ts new file mode 100644 index 0000000..cb25648 --- /dev/null +++ b/rules/enforce-store-naming-convention/prefix/examples/incorrect-store-after-destruction.ts @@ -0,0 +1,9 @@ +import { createStore } from "effector"; + +function createCustomStore() { + return [createStore(null)]; +} + +const [justStore] = createCustomStore(); + +export { justStore }; diff --git a/utils/node-name.js b/utils/node-name.js new file mode 100644 index 0000000..1ffefcb --- /dev/null +++ b/utils/node-name.js @@ -0,0 +1,5 @@ +function nodeName(node) { + return node.id?.name ?? node.name; +} + +module.exports = { nodeName }; diff --git a/utils/node-range.js b/utils/node-range.js new file mode 100644 index 0000000..0b4754e --- /dev/null +++ b/utils/node-range.js @@ -0,0 +1,5 @@ +function nodeRange(node) { + return node.id?.range ?? node.range; +} + +module.exports = { nodeRange }; diff --git a/utils/traverse-real-declaration.js b/utils/traverse-real-declaration.js new file mode 100644 index 0000000..7a7e4d1 --- /dev/null +++ b/utils/traverse-real-declaration.js @@ -0,0 +1,9 @@ +function traverseRealDeclaration(node) { + if (node?.id?.type === "ArrayPattern") { + return node.id.elements; + } + + return [node]; +} + +module.exports = { traverseRealDeclaration };