From 780dcd6d01fba7e98fd2d085bd197dd8e80356b5 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 16 Aug 2024 11:57:01 -0400 Subject: [PATCH 1/3] Update [ghstack-poisoned] --- .../__tests__/ReactCompilerRule-test.ts | 33 ++++++++++++ .../src/rules/ReactCompilerRule.ts | 51 ++++++++++++++++++- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts index c87bcadbe98bc..386f95c493fd9 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts @@ -104,6 +104,17 @@ const tests: CompilerTestCases = { } `, }, + { + name: "'use no forget' directive is respected when errors are present", + code: normalizeIndent` + let count = 0; + function Component() { + 'use no forget'; + count++; + return
Hello world {count}
+ } + `, + }, ], invalid: [ { @@ -199,6 +210,28 @@ const tests: CompilerTestCases = { }, ], }, + { + only: true, + name: "Unused 'use no forget' directive is reported when no errors are present", + code: normalizeIndent` + function Component() { + 'use no forget'; + return
Hello world
+ } + `, + errors: [ + { + message: "Unused 'use no forget' directive", + suggestions: [ + { + output: + // yuck + '\nfunction Component() {\n \n return
Hello world
\n}\n', + }, + ], + }, + ], + }, ], }; diff --git a/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts b/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts index 2fe34a0b7ff2b..27a600fe0cab5 100644 --- a/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts +++ b/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts @@ -15,10 +15,12 @@ import BabelPluginReactCompiler, { ErrorSeverity, parsePluginOptions, validateEnvironmentConfig, + OPT_OUT_DIRECTIVES, type PluginOptions, } from 'babel-plugin-react-compiler/src'; import {Logger} from 'babel-plugin-react-compiler/src/Entrypoint'; import type {Rule} from 'eslint'; +import {Statement} from 'estree'; import * as HermesParser from 'hermes-parser'; type CompilerErrorDetailWithLoc = Omit & { @@ -146,6 +148,7 @@ const rule: Rule.RuleModule = { userOpts['__unstable_donotuse_reportAllBailouts']; } + let shouldReportUnusedOptOutDirective = true; const options: PluginOptions = { ...parsePluginOptions(userOpts), ...COMPILER_OPTIONS, @@ -155,6 +158,7 @@ const rule: Rule.RuleModule = { logEvent: (filename, event): void => { userLogger?.logEvent(filename, event); if (event.kind === 'CompileError') { + shouldReportUnusedOptOutDirective = false; const detail = event.detail; const suggest = makeSuggestions(detail); if (__unstable_donotuse_reportAllBailouts && event.fnLoc != null) { @@ -269,7 +273,52 @@ const rule: Rule.RuleModule = { /* errors handled by injected logger */ } } - return {}; + + function reportUnusedOptOutDirective(stmt: Statement) { + if ( + stmt.type === 'ExpressionStatement' && + stmt.expression.type === 'Literal' && + typeof stmt.expression.value === 'string' && + OPT_OUT_DIRECTIVES.has(stmt.expression.value) && + stmt.loc != null + ) { + context.report({ + message: `Unused '${stmt.expression.value}' directive`, + loc: stmt.loc, + suggest: [ + { + desc: 'Remove the directive', + fix(fixer) { + return fixer.remove(stmt); + }, + }, + ], + }); + } + } + if (shouldReportUnusedOptOutDirective) { + return { + FunctionDeclaration(fnDecl) { + for (const stmt of fnDecl.body.body) { + reportUnusedOptOutDirective(stmt); + } + }, + ArrowFunctionExpression(fnExpr) { + if (fnExpr.body.type === 'BlockStatement') { + for (const stmt of fnExpr.body.body) { + reportUnusedOptOutDirective(stmt); + } + } + }, + FunctionExpression(fnExpr) { + for (const stmt of fnExpr.body.body) { + reportUnusedOptOutDirective(stmt); + } + }, + }; + } else { + return {}; + } }, }; From bbfa62459446b3aa2e1ec727ceb4dab0d44403b6 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 16 Aug 2024 12:07:50 -0400 Subject: [PATCH 2/3] Update [ghstack-poisoned] --- .../__tests__/ReactCompilerRule-test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts index 386f95c493fd9..75bdba02f9f1d 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts @@ -211,7 +211,6 @@ const tests: CompilerTestCases = { ], }, { - only: true, name: "Unused 'use no forget' directive is reported when no errors are present", code: normalizeIndent` function Component() { From c4126772e73aac66b1f973cd7f7dbe85d88354af Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 16 Aug 2024 15:19:37 -0400 Subject: [PATCH 3/3] Update [ghstack-poisoned] --- .../__tests__/ReactCompilerRule-test.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts index 0cd28702ae8b7..c3708ba2e4726 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts @@ -217,7 +217,7 @@ const tests: CompilerTestCases = { ], }, { - name: "Unused 'use no forget' directive is reported when no errors are present", + name: "Unused 'use no forget' directive is reported when no errors are present on components", code: normalizeIndent` function Component() { 'use no forget'; @@ -237,6 +237,27 @@ const tests: CompilerTestCases = { }, ], }, + { + name: "Unused 'use no forget' directive is reported when no errors are present on non-components or hooks", + code: normalizeIndent` + function notacomponent() { + 'use no forget'; + return 1 + 1; + } + `, + errors: [ + { + message: "Unused 'use no forget' directive", + suggestions: [ + { + output: + // yuck + '\nfunction notacomponent() {\n \n return 1 + 1;\n}\n', + }, + ], + }, + ], + }, ], };