eslint-plugin-react-component-name
Version:
Eslint plugin for converting decorated anonymous functions to named functions.
1 lines • 4.67 kB
Source Map (JSON)
{"version":3,"file":"react-component-name.mjs","sources":["../../../../../src/rules/react-component-name.ts"],"sourcesContent":["import type { Rule } from \"eslint\";\nimport type { FunctionExpression, ArrowFunctionExpression } from \"estree\";\n\nconst handler =\n (context: Rule.RuleContext, target: string) =>\n (node: FunctionExpression | ArrowFunctionExpression): void => {\n // @ts-ignore TODO\n let parent = node.parent?.parent;\n while (parent && parent.type !== \"VariableDeclarator\") {\n parent = parent.parent;\n }\n // @ts-ignore TODO\n const parentVarName = parent?.id?.name;\n\n // @ts-ignore TODO\n const functionName = node.id?.name;\n\n if (parentVarName ? functionName !== parentVarName : !functionName) {\n context.report({\n node,\n messageId: \"noAnonymousFunction\",\n fix:\n parentVarName &&\n ((fixer) => {\n const sourceCode = context.getSourceCode();\n const newName = parentVarName;\n const params = node.params\n .map((param) => sourceCode.getText(param))\n .join(\", \");\n\n if (node.type === \"ArrowFunctionExpression\") {\n const arrowBody = sourceCode.getText(node.body);\n const needsBrackets = node.body.type !== \"BlockStatement\";\n const newBody = needsBrackets\n ? `{ return ${arrowBody}; }`\n : arrowBody;\n return fixer.replaceText(\n node,\n `function ${newName}(${params}) ${newBody}`\n );\n }\n\n const functionBody = sourceCode.getText(node.body);\n return fixer.replaceText(\n node,\n `function ${newName}(${params}) ${functionBody}`\n );\n }),\n });\n }\n };\n\nconst create: Rule.RuleModule[\"create\"] = (context) => {\n const options = context.options[0] as { targets: string[] } | undefined;\n const targets = options?.targets || [\"memo\", \"forwardRef\"];\n\n const rules: Rule.RuleListener = {};\n for (const target of targets) {\n const selector = `CallExpression[callee.name=\"${target}\"] > :function, CallExpression[callee.object.name=\"React\"][callee.property.name=\"${target}\"] > :function`;\n rules[selector] = handler(context, target);\n }\n\n return rules;\n};\n\nconst rule = {\n create,\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Ensure named functions are used with specific React helpers\",\n category: \"Best Practices\",\n recommended: true,\n },\n messages: {\n noAnonymousFunction:\n \"Function should have a name matching its parent variable.\",\n },\n fixable: \"code\",\n schema: [\n {\n type: \"object\",\n properties: {\n targets: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"List of a component decorators to enforce named functions.\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n} satisfies Rule.RuleModule;\n\nexport default rule;\n"],"names":[],"mappings":"AAGA,MAAM,UACJ,CAAC,SAA2B,WAC5B,CAAC,SAA6D;AAFhE;AAIQ,MAAA,UAAS,UAAK,WAAL,mBAAa;AACnB,SAAA,UAAU,OAAO,SAAS,sBAAsB;AACrD,aAAS,OAAO;AAAA,EAAA;AAGZ,QAAA,iBAAgB,sCAAQ,OAAR,mBAAY;AAG5B,QAAA,gBAAe,UAAK,OAAL,mBAAS;AAE9B,MAAI,gBAAgB,iBAAiB,gBAAgB,CAAC,cAAc;AAClE,YAAQ,OAAO;AAAA,MACb;AAAA,MACA,WAAW;AAAA,MACX,KACE,kBACC,CAAC,UAAU;AACJ,cAAA,aAAa,QAAQ,cAAc;AACzC,cAAM,UAAU;AAChB,cAAM,SAAS,KAAK,OACjB,IAAI,CAAC,UAAU,WAAW,QAAQ,KAAK,CAAC,EACxC,KAAK,IAAI;AAER,YAAA,KAAK,SAAS,2BAA2B;AAC3C,gBAAM,YAAY,WAAW,QAAQ,KAAK,IAAI;AACxC,gBAAA,gBAAgB,KAAK,KAAK,SAAS;AACzC,gBAAM,UAAU,gBACZ,YAAY,SAAS,QACrB;AACJ,iBAAO,MAAM;AAAA,YACX;AAAA,YACA,YAAY,OAAO,IAAI,MAAM,KAAK,OAAO;AAAA,UAC3C;AAAA,QAAA;AAGF,cAAM,eAAe,WAAW,QAAQ,KAAK,IAAI;AACjD,eAAO,MAAM;AAAA,UACX;AAAA,UACA,YAAY,OAAO,IAAI,MAAM,KAAK,YAAY;AAAA,QAChD;AAAA,MACF;AAAA,IAAA,CACH;AAAA,EAAA;AAEL;AAEF,MAAM,SAAoC,CAAC,YAAY;AAC/C,QAAA,UAAU,QAAQ,QAAQ,CAAC;AACjC,QAAM,WAAU,mCAAS,YAAW,CAAC,QAAQ,YAAY;AAEzD,QAAM,QAA2B,CAAC;AAClC,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,+BAA+B,MAAM,oFAAoF,MAAM;AAChJ,UAAM,QAAQ,IAAI,QAAQ,OAAe;AAAA,EAAA;AAGpC,SAAA;AACT;AAEA,MAAM,OAAO;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aACE;AAAA,MACF,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,qBACE;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,IACT,QAAQ;AAAA,MACN;AAAA,QACE,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,YACP,MAAM;AAAA,YACN,OAAO,EAAE,MAAM,SAAS;AAAA,YACxB,aACE;AAAA,UAAA;AAAA,QAEN;AAAA,QACA,sBAAsB;AAAA,MAAA;AAAA,IACxB;AAAA,EACF;AAEJ;"}