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 3955746176..bf7d2ca62c 100644 --- a/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts +++ b/compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts @@ -15,7 +15,7 @@ import ReactCompilerRule from "../src/rules/ReactCompilerRule"; */ function normalizeIndent(strings: TemplateStringsArray): string { const codeLines = strings[0].split("\n"); - const leftPadding = codeLines[1].match(/\s+/)[0]; + const leftPadding = codeLines[1].match(/\s+/)![0]; return codeLines.map((line) => line.slice(leftPadding.length)).join("\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 7c46cf0b88..dff3475ccb 100644 --- a/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts +++ b/compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts @@ -6,22 +6,22 @@ */ import { transformFromAstSync } from "@babel/core"; -// @ts-expect-error +// @ts-expect-error: no types available import PluginProposalPrivateMethods from "@babel/plugin-proposal-private-methods"; import type { SourceLocation as BabelSourceLocation } from "@babel/types"; import BabelPluginReactCompiler, { + CompilerErrorDetailOptions, CompilerSuggestionOperation, ErrorSeverity, parsePluginOptions, validateEnvironmentConfig, type CompilerError, - type CompilerErrorDetail, type PluginOptions, } from "babel-plugin-react-compiler/src"; import type { Rule } from "eslint"; import * as HermesParser from "hermes-parser"; -type CompilerErrorDetailWithLoc = Omit & { +type CompilerErrorDetailWithLoc = Omit & { loc: BabelSourceLocation; }; @@ -40,7 +40,7 @@ const DEFAULT_REPORTABLE_LEVELS = new Set([ let reportableLevels = DEFAULT_REPORTABLE_LEVELS; function isReportableDiagnostic( - detail: CompilerErrorDetail + detail: CompilerErrorDetailOptions ): detail is CompilerErrorDetailWithLoc { return ( reportableLevels.has(detail.severity) && @@ -49,6 +49,59 @@ function isReportableDiagnostic( ); } +function makeSuggestions( + detail: CompilerErrorDetailOptions +): Array { + let suggest: Array = []; + if (Array.isArray(detail.suggestions)) { + for (const suggestion of detail.suggestions) { + switch (suggestion.op) { + case CompilerSuggestionOperation.InsertBefore: + suggest.push({ + desc: suggestion.description, + fix(fixer) { + return fixer.insertTextBeforeRange( + suggestion.range, + suggestion.text + ); + }, + }); + break; + case CompilerSuggestionOperation.InsertAfter: + suggest.push({ + desc: suggestion.description, + fix(fixer) { + return fixer.insertTextAfterRange( + suggestion.range, + suggestion.text + ); + }, + }); + break; + case CompilerSuggestionOperation.Replace: + suggest.push({ + desc: suggestion.description, + fix(fixer) { + return fixer.replaceTextRange(suggestion.range, suggestion.text); + }, + }); + break; + case CompilerSuggestionOperation.Remove: + suggest.push({ + desc: suggestion.description, + fix(fixer) { + return fixer.removeRange(suggestion.range); + }, + }); + break; + default: + assertExhaustive(suggestion, "Unhandled suggestion operation"); + } + } + } + return suggest; +} + const COMPILER_OPTIONS: Partial = { noEmit: true, compilationMode: "infer", @@ -96,7 +149,7 @@ const rule: Rule.RuleModule = { function hasFlowSuppression( nodeLoc: BabelSourceLocation, suppression: string - ) { + ): boolean { const sourceCode = context.getSourceCode(); const comments = sourceCode.getAllComments(); const flowSuppressionRegex = new RegExp( @@ -122,7 +175,9 @@ const rule: Rule.RuleModule = { sourceType: "unambiguous", plugins: ["typescript", "jsx"], }); - } catch {} + } catch { + /* empty */ + } } else { try { babelAST = HermesParser.parse(sourceCode, { @@ -131,7 +186,9 @@ const rule: Rule.RuleModule = { sourceFilename: filename, sourceType: "module", }); - } catch {} + } catch { + /* empty */ + } } if (babelAST != null) { @@ -158,63 +215,10 @@ const rule: Rule.RuleModule = { // If Flow already caught this error, we don't need to report it again. continue; } - let suggest: Array = []; - if (Array.isArray(detail.suggestions)) { - for (const suggestion of detail.suggestions) { - switch (suggestion.op) { - case CompilerSuggestionOperation.InsertBefore: - suggest.push({ - desc: suggestion.description, - fix(fixer) { - return fixer.insertTextBeforeRange( - suggestion.range, - suggestion.text - ); - }, - }); - break; - case CompilerSuggestionOperation.InsertAfter: - suggest.push({ - desc: suggestion.description, - fix(fixer) { - return fixer.insertTextAfterRange( - suggestion.range, - suggestion.text - ); - }, - }); - break; - case CompilerSuggestionOperation.Replace: - suggest.push({ - desc: suggestion.description, - fix(fixer) { - return fixer.replaceTextRange( - suggestion.range, - suggestion.text - ); - }, - }); - break; - case CompilerSuggestionOperation.Remove: - suggest.push({ - desc: suggestion.description, - fix(fixer) { - return fixer.removeRange(suggestion.range); - }, - }); - break; - default: - assertExhaustive( - suggestion, - "Unhandled suggestion operation" - ); - } - } - } context.report({ message: detail.reason, loc: detail.loc, - suggest, + suggest: makeSuggestions(detail), }); } } else { diff --git a/compiler/yarn.lock b/compiler/yarn.lock index f54b9be27d..2bd1ad8559 100644 --- a/compiler/yarn.lock +++ b/compiler/yarn.lock @@ -10072,4 +10072,4 @@ zod-validation-error@^3.0.3: zod@^3.22.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" - integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== \ No newline at end of file