@samitouri / QOS-React-2 / commits / dda59d093a

Add InvalidJS error severity

Lauren Tan committed Jun 28, 2023 at 11:43 UTC dda59d093a9dae733f674ba91557a2ac7c1cb61b
4 files changed +56 -37
compiler/forget/apps/playground/lib/forgetMonacoDiagnostics.ts
+2 -3
@@ -19,10 +19,9 @@ function mapForgetSeverityToMonaco(
19 ): MarkerSeverity {
20 switch (level) {
21 case ErrorSeverity.Todo:
22 - case ErrorSeverity.InvalidInput:
23 - return monaco.MarkerSeverity.Error;
24 - default:
22 return monaco.MarkerSeverity.Warning;
23 + default:
24 + return monaco.MarkerSeverity.Error;
25 }
26 }
27
compiler/forget/packages/babel-plugin-react-forget/src/CompilerError.ts
+5 -5
@@ -10,9 +10,9 @@ import { assertExhaustive } from "./Utils/utils";
10
11 export enum ErrorSeverity {
12 /**
13 - * Unexpected syntax or input that may not be safe to compile.
13 + * Invalid JS syntax, or valid syntax that is semantically invalid which may indicate some misunderstanding on the user’s part.
14 */
15 - InvalidInput = "InvalidInput",
15 + InvalidJS = "InvalidJS",
16 /**
17 * Code that breaks the rules of React.
18 */
@@ -132,14 +132,14 @@ export class CompilerError extends Error {
132 throw errors;
133 }
134
135 - static invalidInput(
135 + static invalidJS(
136 options: Omit<CompilerErrorDetailOptions, "severity">
137 ): never {
138 const errors = new CompilerError();
139 errors.pushErrorDetail(
140 new CompilerErrorDetail({
141 ...options,
142 - severity: ErrorSeverity.InvalidInput,
142 + severity: ErrorSeverity.InvalidJS,
143 })
144 );
145 throw errors;
@@ -215,7 +215,7 @@ export class CompilerError extends Error {
215 return this.details.some((detail) => {
216 switch (detail.severity) {
217 case ErrorSeverity.Invariant:
218 - case ErrorSeverity.InvalidInput:
218 + case ErrorSeverity.InvalidJS:
219 case ErrorSeverity.InvalidReact:
220 case ErrorSeverity.InvalidConfig:
221 return true;
compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+42 -25
@@ -8,7 +8,11 @@
8 import { NodePath, Scope } from "@babel/traverse";
9 import * as t from "@babel/types";
10 import { Expression } from "@babel/types";
11 -import { CompilerError, ErrorSeverity } from "../CompilerError";
11 +import {
12 + CompilerError,
13 + CompilerSuggestionOperation,
14 + ErrorSeverity,
15 +} from "../CompilerError";
16 import { Err, Ok, Result } from "../Utils/Result";
17 import { assertExhaustive } from "../Utils/utils";
18 import { Environment } from "./Environment";
@@ -142,8 +146,8 @@ export function lower(
146 lowerStatement(builder, body);
147 } else {
148 builder.errors.push({
145 - reason: `(BuildHIR::lower) Unexpected function body kind: ${body.type}}`,
146 - severity: ErrorSeverity.InvalidInput,
149 + reason: `Unexpected function body kind: ${body.type}}. This error is likely caused by a bug in React Forget. Please file an issue`,
150 + severity: ErrorSeverity.InvalidJS,
151 loc: body.node.loc ?? null,
152 suggestions: null,
153 });
@@ -541,9 +545,8 @@ function lowerStatement(
545 if (testExpr.node == null) {
546 if (hasDefault) {
547 builder.errors.push({
544 - reason:
545 - "(BuildHIR::lowerStatement) Expected at most one `default` branch in SwitchStatement, this code should have failed to parse",
546 - severity: ErrorSeverity.InvalidInput,
548 + reason: `Expected at most one \`default\` branch in SwitchStatement, this code should have failed to parse. This error is likely caused by a bug in React Forget. Please file an issue`,
549 + severity: ErrorSeverity.InvalidJS,
550 loc: case_.node.loc ?? null,
551 suggestions: null,
552 });
@@ -659,11 +662,19 @@ function lowerStatement(
662 };
663 if (builder.isContextIdentifier(id)) {
664 if (kind === InstructionKind.Const) {
665 + const declRangeStart = declaration.parentPath.node.start!;
666 builder.errors.push({
663 - reason: `(BuildHIR::lowerAssignment) Invalid declaration kind (const) for variable later reassigned.`,
664 - severity: ErrorSeverity.InvalidInput,
667 + reason: `Invalid declaration kind (const), this variable is reassigned later`,
668 + severity: ErrorSeverity.InvalidJS,
669 loc: id.node.loc ?? null,
666 - suggestions: null,
670 + suggestions: [
671 + {
672 + description: "Change to let",
673 + op: CompilerSuggestionOperation.Replace,
674 + range: [declRangeStart, declRangeStart + 5], // "const".length
675 + text: "let",
676 + },
677 + ],
678 });
679 }
680 lowerValueToTemporary(builder, {
@@ -687,8 +698,8 @@ function lowerStatement(
698 }
699 } else {
700 builder.errors.push({
690 - reason: `(BuildHIR::lowerStatement) Expected variable declaration to be an identifier if no initializer was provided.`,
691 - severity: ErrorSeverity.InvalidInput,
701 + reason: `Expected variable declaration to be an identifier if no initializer was provided. This error is likely caused by a bug in React Forget. Please file an issue`,
702 + severity: ErrorSeverity.InvalidJS,
703 loc: stmt.node.loc ?? null,
704 suggestions: null,
705 });
@@ -1109,8 +1120,8 @@ function lowerExpression(
1120 const calleePath = expr.get("callee");
1121 if (!calleePath.isExpression()) {
1122 builder.errors.push({
1112 - reason: `(BuildHIR::lowerExpression) Expected Expression, got ${calleePath.type} in NewExpression (v8 intrinsics not supported): ${calleePath.type}`,
1113 - severity: ErrorSeverity.Todo,
1123 + reason: `Expected Expression, got ${calleePath.type} in NewExpression (v8 intrinsics not supported): ${calleePath.type}. This error is likely caused by a bug in React Forget. Please file an issue`,
1124 + severity: ErrorSeverity.InvalidJS,
1125 loc: calleePath.node.loc ?? null,
1126 suggestions: null,
1127 });
@@ -1135,7 +1146,7 @@ function lowerExpression(
1146 const calleePath = expr.get("callee");
1147 if (!calleePath.isExpression()) {
1148 builder.errors.push({
1138 - reason: `(BuildHIR::lowerExpression) Expected Expression, got ${calleePath.type} in CallExpression (v8 intrinsics not supported)`,
1149 + reason: `Expected Expression, got ${calleePath.type} in CallExpression (v8 intrinsics not supported). This error is likely caused by a bug in React Forget. Please file an issue`,
1150 severity: ErrorSeverity.Todo,
1151 loc: calleePath.node.loc ?? null,
1152 suggestions: null,
@@ -1201,8 +1212,8 @@ function lowerExpression(
1212 }
1213 if (last === null) {
1214 builder.errors.push({
1204 - reason: `(BuildHIR::lowerExpression) Expected SequenceExpression to have at least one expression`,
1205 - severity: ErrorSeverity.InvalidInput,
1215 + reason: `Expected SequenceExpression to have at least one expression. This error is likely caused by a bug in React Forget. Please file an issue`,
1216 + severity: ErrorSeverity.InvalidJS,
1217 loc: expr.node.loc ?? null,
1218 suggestions: null,
1219 });
@@ -1658,8 +1669,8 @@ function lowerExpression(
1669
1670 if (subexprs.length !== quasis.length - 1) {
1671 builder.errors.push({
1661 - reason: `(BuildHIR::lowerExpression) Unexpected quasi and subexpression lengths in TemplateLiteral.`,
1662 - severity: ErrorSeverity.InvalidInput,
1672 + reason: `Unexpected quasi and subexpression lengths in TemplateLiteral. This error is likely caused by a bug in React Forget. Please file an issue`,
1673 + severity: ErrorSeverity.InvalidJS,
1674 loc: exprPath.node.loc ?? null,
1675 suggestions: null,
1676 });
@@ -1710,10 +1721,16 @@ function lowerExpression(
1721 }
1722 } else {
1723 builder.errors.push({
1713 - reason: `(BuildHIR::lowerExpression) delete on a non-member expression has no semantic meaning`,
1714 - severity: ErrorSeverity.InvalidInput,
1724 + reason: `Deleting a non-member expression has no semantic meaning`,
1725 + severity: ErrorSeverity.InvalidJS,
1726 loc: expr.node.loc ?? null,
1716 - suggestions: null,
1727 + suggestions: [
1728 + {
1729 + description: "Remove this line",
1730 + range: [expr.node.start!, expr.node.end!],
1731 + op: CompilerSuggestionOperation.Remove,
1732 + },
1733 + ],
1734 });
1735 return { kind: "UnsupportedNode", node: expr.node, loc: exprLoc };
1736 }
@@ -2291,8 +2308,8 @@ function lowerJsxElementName(
2308 const tag = `${namespace}:${name}`;
2309 if (namespace.indexOf(":") !== -1 || name.indexOf(":") !== -1) {
2310 builder.errors.push({
2294 - reason: `(BuildHIR::lowerJsxElementName) Expected JSXNamespacedName to have no colons in the namespace or name, got '${namespace}' : '${name}'`,
2295 - severity: ErrorSeverity.InvalidInput,
2311 + reason: `Expected JSXNamespacedName to have no colons in the namespace or name, got '${namespace}' : '${name}'. This error is likely caused by a bug in React Forget. Please file an issue`,
2312 + severity: ErrorSeverity.InvalidJS,
2313 loc: exprPath.node.loc ?? null,
2314 suggestions: null,
2315 });
@@ -2585,8 +2602,8 @@ function lowerAssignment(
2602 if (kind !== InstructionKind.Reassign) {
2603 if (kind === InstructionKind.Const) {
2604 builder.errors.push({
2588 - reason: `(BuildHIR::lowerAssignment) Invalid declaration kind (const) for variable later reassigned.`,
2589 - severity: ErrorSeverity.InvalidInput,
2605 + reason: `Invalid declaration kind (const), this variable is reassigned later`,
2606 + severity: ErrorSeverity.InvalidJS,
2607 loc: lvalue.node.loc ?? null,
2608 suggestions: null,
2609 });
compiler/forget/packages/eslint-plugin-react-forget/src/rules/ReactForgetDiagnostics.ts
+7 -4
@@ -32,19 +32,22 @@ function isReactForgetCompilerError(err: Error): err is CompilerError {
32 function isReportableDiagnostic(
33 detail: CompilerErrorDetail
34 ): detail is CompilerErrorDetailWithLoc {
35 - let isCorrectSeverity = false;
35 + let isReportable = false;
36 switch (detail.severity) {
37 case ErrorSeverity.InvalidReact:
38 - case ErrorSeverity.InvalidInput:
39 - isCorrectSeverity = true;
38 + case ErrorSeverity.InvalidJS:
39 + isReportable = true;
40 break;
41 + case ErrorSeverity.InvalidConfig:
42 case ErrorSeverity.Invariant:
43 case ErrorSeverity.Todo:
44 break;
45 + default:
46 + assertExhaustive(detail.severity, "Unhandled error severity");
47 }
48
49 return (
47 - isCorrectSeverity === true &&
50 + isReportable === true &&
51 detail.loc != null &&
52 typeof detail.loc !== "symbol"
53 );