main
mjs 110 lines 3.44 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 /**
9 * Debug error printer for the Rust port testing infrastructure.
10 *
11 * Prints a detailed representation of CompilerError/CompilerDiagnostic objects,
12 * including all fields: category, severity, reason, description, loc,
13 * suggestions, and nested details.
14 *
15 * Format matches the testing infrastructure plan:
16 *
17 * Error:
18 * category: InvalidReact
19 * severity: InvalidReact
20 * reason: "Hooks must be called unconditionally"
21 * description: "Cannot call a hook (useState) conditionally"
22 * loc: 3:4-3:20
23 * suggestions: []
24 * details:
25 * - kind: error
26 * loc: 2:2-5:3
27 * message: "This is a conditional"
28 */
29
30 /**
31 * Format a source location for debug output.
32 * @param {object|symbol|null} loc
33 * @returns {string}
34 */
35 export function formatSourceLocation(loc) {
36 if (loc == null || typeof loc === "symbol") {
37 return "generated";
38 }
39 return `${loc.start.line}:${loc.start.column}-${loc.end.line}:${loc.end.column}`;
40 }
41
42 /**
43 * Format a CompilerError (with details array) into a debug string.
44 * @param {object} error - A CompilerError instance
45 * @returns {string}
46 */
47 export function debugPrintError(error) {
48 const lines = [];
49
50 if (error.details && error.details.length > 0) {
51 for (const detail of error.details) {
52 lines.push("Error:");
53 lines.push(` category: ${detail.category ?? "unknown"}`);
54 lines.push(` severity: ${detail.severity ?? "unknown"}`);
55 lines.push(` reason: ${JSON.stringify(detail.reason ?? "")}`);
56
57 if (detail.description != null) {
58 lines.push(` description: ${JSON.stringify(detail.description)}`);
59 } else {
60 lines.push(` description: null`);
61 }
62
63 // Handle loc: CompilerDiagnostic uses primaryLocation(), CompilerErrorDetail uses .loc
64 const loc =
65 typeof detail.primaryLocation === "function"
66 ? detail.primaryLocation()
67 : detail.loc;
68 lines.push(` loc: ${formatSourceLocation(loc)}`);
69
70 const suggestions = detail.suggestions ?? [];
71 if (suggestions.length === 0) {
72 lines.push(` suggestions: []`);
73 } else {
74 lines.push(` suggestions:`);
75 for (const s of suggestions) {
76 lines.push(` - op: ${s.op}`);
77 lines.push(` range: [${s.range[0]}, ${s.range[1]}]`);
78 lines.push(` description: ${JSON.stringify(s.description)}`);
79 if (s.text != null) {
80 lines.push(` text: ${JSON.stringify(s.text)}`);
81 }
82 }
83 }
84
85 // Handle details array for CompilerDiagnostic (new-style errors)
86 if (
87 detail.options &&
88 detail.options.details &&
89 detail.options.details.length > 0
90 ) {
91 lines.push(` details:`);
92 for (const d of detail.options.details) {
93 if (d.kind === "error") {
94 lines.push(` - kind: error`);
95 lines.push(` loc: ${formatSourceLocation(d.loc)}`);
96 lines.push(` message: ${JSON.stringify(d.message)}`);
97 } else if (d.kind === "hint") {
98 lines.push(` - kind: hint`);
99 lines.push(` message: ${JSON.stringify(d.message)}`);
100 }
101 }
102 }
103 }
104 } else {
105 lines.push("Error:");
106 lines.push(` message: ${JSON.stringify(error.message)}`);
107 }
108
109 return lines.join("\n") + "\n";
110 }