diff --git a/.vscode/settings.json b/.vscode/settings.json index 7dbd288..abf27bb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "conventionalCommits.scopes": [ - "binaries" + "binaries", + "rules" ] } \ No newline at end of file diff --git a/grit/react-effects.grit b/grit/react-effects.grit index 8fd242a..c5abc3a 100644 --- a/grit/react-effects.grit +++ b/grit/react-effects.grit @@ -232,6 +232,7 @@ any { $body <: contains `if ($condition) { $ifBody }`, $condition <: not contains `!ignore`, $condition <: not contains `error`, + $body <: not contains `return $cleanup`, $body <: not contains `return () =>`, $body <: not contains `return function`, register_diagnostic(span=$effect, message="Avoid using state as an event handler. Instead, call the event handler directly.") @@ -241,6 +242,7 @@ any { $body <: contains `if ($condition) { $ifBody }`, $condition <: not contains `!ignore`, $condition <: not contains `error`, + $body <: not contains `return $cleanup`, $body <: not contains `return () =>`, $body <: not contains `return function`, register_diagnostic(span=$effect, message="Avoid using state as an event handler. Instead, call the event handler directly.") diff --git a/tests/fixtures/suppression.tsx b/tests/fixtures/suppression.tsx new file mode 100644 index 0000000..fcfcdaa --- /dev/null +++ b/tests/fixtures/suppression.tsx @@ -0,0 +1,8 @@ +import { useEffect } from 'react'; + +export function EmptyEffectComponent() { + // biome-ignore lint: This comment should suppress the empty effect warning + useEffect(() => {}, []); + + return
Empty Effect
; +} diff --git a/tests/fixtures/valid-editor-transform-effect.tsx b/tests/fixtures/valid-editor-transform-effect.tsx new file mode 100644 index 0000000..2f6fd20 --- /dev/null +++ b/tests/fixtures/valid-editor-transform-effect.tsx @@ -0,0 +1,26 @@ +import { useEffect } from 'react'; + +declare const ParagraphNode: unknown; + +type Editor = { + registerNodeTransform: ( + node: unknown, + callback: (node: { getTextContent: () => string; remove: () => void }) => void, + ) => () => void; +}; + +declare function useEditor(): Editor; + +export function ValidEditorTransformEffect() { + const editor = useEditor(); + + useEffect(() => { + return editor.registerNodeTransform(ParagraphNode, (node) => { + if (node.getTextContent().trim() === '') { + node.remove(); + } + }); + }, [editor]); + + return null; +} diff --git a/tests/plugin.test.ts b/tests/plugin.test.ts index dd77676..bad250e 100644 --- a/tests/plugin.test.ts +++ b/tests/plugin.test.ts @@ -79,4 +79,14 @@ describe('unnecessary-effect plugin', () => { const { exitCode } = runBiome(resolve(FIXTURES_PATH, 'valid-effect.tsx')); expect(exitCode).toBe(0); }); + + test('should not report registering editor transforms', () => { + const { exitCode } = runBiome(resolve(FIXTURES_PATH, 'valid-editor-transform-effect.tsx')); + expect(exitCode).toBe(0); + }); + + test('should respect suppression comments', () => { + const { exitCode } = runBiome(resolve(FIXTURES_PATH, 'suppression.tsx')); + expect(exitCode).toBe(0); + }); });