From 962043b4cb9295ca0d3337bb4d933d2d457fdec8 Mon Sep 17 00:00:00 2001 From: Noah Manneschmidt Date: Fri, 11 Nov 2022 11:10:02 -0800 Subject: [PATCH] Add config to allow jsx in classes (#10) --- .nvmrc | 2 +- src/prefer-function-component/index.ts | 21 +++++++++++++++++---- src/prefer-function-component/test.ts | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.nvmrc b/.nvmrc index 6b17d22..431076a 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -14.16.1 +16.16.0 diff --git a/src/prefer-function-component/index.ts b/src/prefer-function-component/index.ts index 9eed086..0f9ee4b 100644 --- a/src/prefer-function-component/index.ts +++ b/src/prefer-function-component/index.ts @@ -6,6 +6,7 @@ import type { Rule } from "eslint"; export const COMPONENT_SHOULD_BE_FUNCTION = "componentShouldBeFunction"; export const ALLOW_COMPONENT_DID_CATCH = "allowComponentDidCatch"; +export const ALLOW_JSX_IN_CLASSES = "allowJsxInClasses"; const COMPONENT_DID_CATCH = "componentDidCatch"; // https://eslint.org/docs/developer-guide/working-with-rules const PROGRAM_EXIT = "Program:exit"; @@ -40,6 +41,10 @@ const rule: Rule.RuleModule = { default: true, type: "boolean", }, + [ALLOW_JSX_IN_CLASSES]: { + default: false, + type: "boolean", + }, }, additionalProperties: false, }, @@ -49,6 +54,8 @@ const rule: Rule.RuleModule = { create(context: Rule.RuleContext) { const allowComponentDidCatch = context.options[0]?.allowComponentDidCatch ?? true; + const allowJsxInClasses = + context.options[0]?.allowComponentDidCatch ?? false; function shouldPreferFunction(node: Node): boolean { const properties = node.body.body; @@ -72,14 +79,20 @@ const rule: Rule.RuleModule = { } } + function detectJsxInClass(node: Node): void { + if (!allowJsxInClasses) { + detect(node); + } + } + return { - "ClassDeclaration:has(JSXElement)": detect, - "ClassDeclaration:has(JSXFragment)": detect, + "ClassDeclaration:has(JSXElement)": detectJsxInClass, + "ClassDeclaration:has(JSXFragment)": detectJsxInClass, "ClassDeclaration[superClass.object.name='React'][superClass.property.name='Component']": detect, "ClassDeclaration[superClass.name='Component']": detect, - "ClassExpression:has(JSXElement)": detect, - "ClassExpression:has(JSXFragment)": detect, + "ClassExpression:has(JSXElement)": detectJsxInClass, + "ClassExpression:has(JSXFragment)": detectJsxInClass, "ClassExpression[superClass.object.name='React'][superClass.property.name='Component']": detect, "ClassExpression[superClass.name='Component']": detect, diff --git a/src/prefer-function-component/test.ts b/src/prefer-function-component/test.ts index 493cceb..fe555bc 100644 --- a/src/prefer-function-component/test.ts +++ b/src/prefer-function-component/test.ts @@ -1,6 +1,7 @@ import { RuleTester } from "eslint"; import rule, { ALLOW_COMPONENT_DID_CATCH, + ALLOW_JSX_IN_CLASSES, COMPONENT_SHOULD_BE_FUNCTION, } from "."; @@ -77,6 +78,21 @@ ruleTester.run("prefer-function-component", rule, { }; `, }, + { + // non-component class with JSX + code: ` + class Foo { + getBar() { + return ; + } + }; + `, + options: [ + { + [ALLOW_JSX_IN_CLASSES]: true, + }, + ], + }, { // object with JSX code: `