From 9c033a481d41252d88f05668723f7e061d37f562 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Thu, 22 Jun 2023 10:18:43 -0400 Subject: [PATCH] [eslint-plugin] Only report on InvalidInput errors Invariants aren't actionable by users, so we can omit reporting them in eslint as errors (while continuing to throw in the compiler itself) --- .../babel-plugin-react-forget/src/index.ts | 2 +- .../__tests__/ReactForgetDiagnostics-test.ts | 41 ++++++++----------- .../eslint-plugin-react-forget/package.json | 1 + .../src/rules/ReactForgetDiagnostics.ts | 31 +++++++++++++- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/index.ts b/compiler/forget/packages/babel-plugin-react-forget/src/index.ts index 5b644863d1..669f53022f 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/index.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/index.ts @@ -19,7 +19,7 @@ export { parsePluginOptions, run, } from "./Entrypoint"; -export { Effect, Hook, ValueKind, printHIR } from "./HIR"; +export { Effect, Hook, SourceLocation, ValueKind, printHIR } from "./HIR"; export { printReactiveFunction } from "./ReactiveScopes"; declare global { diff --git a/compiler/forget/packages/eslint-plugin-react-forget/__tests__/ReactForgetDiagnostics-test.ts b/compiler/forget/packages/eslint-plugin-react-forget/__tests__/ReactForgetDiagnostics-test.ts index a2e0fb8dac..249325e4b6 100644 --- a/compiler/forget/packages/eslint-plugin-react-forget/__tests__/ReactForgetDiagnostics-test.ts +++ b/compiler/forget/packages/eslint-plugin-react-forget/__tests__/ReactForgetDiagnostics-test.ts @@ -41,6 +41,22 @@ const tests: ForgetTestCases = { } `, }, + { + // OK because invariants are only meant for the compiler team's consumption + name: "[Invariant] Defined after use", + code: normalizeIndent` + function Component(props) { + 'use forget'; + let y = function () { + m(x); + }; + + let x = { a }; + m(x); + return y; + } + `, + }, ], invalid: [ { @@ -64,31 +80,6 @@ const tests: ForgetTestCases = { }, ], }, - { - name: "[Invariant] Defined after use", - code: normalizeIndent` - function Component(props) { - 'use forget'; - let y = function () { - m(x); - }; - - let x = { a }; - m(x); - return y; - } - `, - errors: [ - { - message: - "[ReactForget] Invariant: EnterSSA: Expected identifier to be defined before being used. Identifier x$1 is undefined (8:8)", - line: 8, - column: 3, - endColumn: 17, - endLine: 8, - }, - ], - }, ], }; diff --git a/compiler/forget/packages/eslint-plugin-react-forget/package.json b/compiler/forget/packages/eslint-plugin-react-forget/package.json index fdad2e8ebb..b7a7b61931 100644 --- a/compiler/forget/packages/eslint-plugin-react-forget/package.json +++ b/compiler/forget/packages/eslint-plugin-react-forget/package.json @@ -30,6 +30,7 @@ "@babel/eslint-parser": "^7.19.1", "@babel/preset-env": "^7.22.4", "@babel/preset-typescript": "^7.18.6", + "@babel/types": "^7.19.0", "@types/node": "^20.2.5", "babel-jest": "^29.0.3", "eslint": "^8.19.0", diff --git a/compiler/forget/packages/eslint-plugin-react-forget/src/rules/ReactForgetDiagnostics.ts b/compiler/forget/packages/eslint-plugin-react-forget/src/rules/ReactForgetDiagnostics.ts index e9a770551c..68355d2eac 100644 --- a/compiler/forget/packages/eslint-plugin-react-forget/src/rules/ReactForgetDiagnostics.ts +++ b/compiler/forget/packages/eslint-plugin-react-forget/src/rules/ReactForgetDiagnostics.ts @@ -6,17 +6,44 @@ */ import { transformFromAstSync } from "@babel/core"; +import type { SourceLocation as BabelSourceLocation } from "@babel/types"; import ReactForgetBabelPlugin, { - CompilerError, + ErrorSeverity, + type CompilerError, + type CompilerErrorDetail, type PluginOptions, } from "babel-plugin-react-forget"; import type { Rule } from "eslint"; import * as HermesParser from "hermes-parser"; +type CompilerErrorDetailWithLoc = Omit & { + loc: BabelSourceLocation; +}; + function isReactForgetCompilerError(err: Error): err is CompilerError { return err.name === "ReactForgetCompilerError"; } +function isReportableDiagnostic( + detail: CompilerErrorDetail +): detail is CompilerErrorDetailWithLoc { + let isCorrectSeverity = false; + switch (detail.severity) { + case ErrorSeverity.InvalidInput: + isCorrectSeverity = true; + break; + case ErrorSeverity.Invariant: + case ErrorSeverity.Todo: + break; + } + + return ( + isCorrectSeverity === true && + detail.loc != null && + typeof detail.loc !== "symbol" + ); +} + const rule: Rule.RuleModule = { meta: { type: "problem", @@ -61,7 +88,7 @@ const rule: Rule.RuleModule = { } catch (err) { if (isReactForgetCompilerError(err) && Array.isArray(err.details)) { for (const detail of err.details) { - if (detail.loc != null && typeof detail.loc !== "symbol") { + if (isReportableDiagnostic(detail)) { context.report({ message: detail.toString(), loc: detail.loc,