UNPKG

@truenine/eslint9-config

Version:

ESLint 9 configuration package for Compose Client projects with TypeScript, Vue, and modern JavaScript support

97 lines (96 loc) 3.3 kB
//#region src/rules/code-style/prefer-lookup-table.ts /** * ESLint rule: prefer-lookup-table * * Detects long chains of `||` checks against the same variable and suggests using a Set lookup or Array.includes. */ const rule = { meta: { type: "suggestion", docs: { description: "Prefer Set.has or Array.includes for multiple equality checks against the same variable", recommended: false }, fixable: "code", schema: [{ type: "object", properties: { threshold: { type: "integer", minimum: 3, default: 4 } }, additionalProperties: false }], messages: { preferLookup: "Found {{count}} checks against the same value. Consider optimizing with a lookup table (Set/Array)." } }, create(context) { const { sourceCode } = context; const threshold = (context.options[0] ?? {}).threshold ?? 4; function getNormalizedText(node) { return sourceCode.getText(node).replaceAll(/\s+/g, ""); } function isEqualityCheck(node) { if (node.type !== "BinaryExpression") return false; const op = node.operator; return op === "===" || op === "=="; } function isPure(node) { return node.type === "Identifier" || node.type === "MemberExpression" || node.type === "Literal"; } function collectConditions(node, operator, conditions = []) { if (node.type === "LogicalExpression" && node.operator === operator) { const logicalNode = node; collectConditions(logicalNode.left, operator, conditions); collectConditions(logicalNode.right, operator, conditions); } else conditions.push(node); return conditions; } const reportSet = /* @__PURE__ */ new Set(); return { LogicalExpression(node) { if (node.operator !== "||") return; if (reportSet.has(node)) return; const currentParent = node.parent; if (currentParent?.type === "LogicalExpression" && currentParent.operator === "||") return; const conditions = collectConditions(node, "||"); if (conditions.length < threshold) return; const subjectMap = /* @__PURE__ */ new Map(); for (const condition of conditions) { if (!isEqualityCheck(condition)) continue; const binExpr = condition; let subject = null; let value = null; if (isPure(binExpr.left) && binExpr.right.type === "Literal") { subject = binExpr.left; value = binExpr.right; } else if (isPure(binExpr.right) && binExpr.left.type === "Literal") { subject = binExpr.right; value = binExpr.left; } if (subject !== null && value !== null) { const subjectKey = getNormalizedText(subject); if (!subjectMap.has(subjectKey)) subjectMap.set(subjectKey, { subject, values: [] }); subjectMap.get(subjectKey).values.push(value); } } for (const [_, { subject, values }] of subjectMap.entries()) if (values.length >= threshold) { context.report({ node, messageId: "preferLookup", data: { count: values.length.toString() }, fix(fixer) { const valuesText = values.map((v) => sourceCode.getText(v)).join(", "); const subjectText = sourceCode.getText(subject); return fixer.replaceText(node, `new Set([${valuesText}]).has(${subjectText})`); } }); break; } } }; } }; //#endregion export { rule as default }; //# sourceMappingURL=prefer-lookup-table.mjs.map