Skip to main content

react_compiler_swc/
diagnostics.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use react_compiler::entrypoint::compile_result::{
7    CompileResult, CompilerErrorDetailInfo, CompilerErrorInfo, LoggerEvent,
8};
9
10#[derive(Debug, Clone)]
11pub enum Severity {
12    Error,
13    Warning,
14}
15
16#[derive(Debug, Clone)]
17pub struct DiagnosticMessage {
18    pub severity: Severity,
19    pub message: String,
20    pub span: Option<(u32, u32)>,
21}
22
23/// Converts a CompileResult into diagnostic messages for display
24pub fn compile_result_to_diagnostics(result: &CompileResult) -> Vec<DiagnosticMessage> {
25    let mut diagnostics = Vec::new();
26
27    match result {
28        CompileResult::Success { events, .. } => {
29            // Process logger events from successful compilation
30            for event in events {
31                if let Some(diag) = event_to_diagnostic(event) {
32                    diagnostics.push(diag);
33                }
34            }
35        }
36        CompileResult::Error {
37            error, events, ..
38        } => {
39            // Add the main error
40            diagnostics.push(error_info_to_diagnostic(error));
41
42            // Process logger events from failed compilation
43            for event in events {
44                if let Some(diag) = event_to_diagnostic(event) {
45                    diagnostics.push(diag);
46                }
47            }
48        }
49    }
50
51    diagnostics
52}
53
54fn error_info_to_diagnostic(error: &CompilerErrorInfo) -> DiagnosticMessage {
55    let message = if let Some(description) = &error.description {
56        format!("[ReactCompiler] {}. {}", error.reason, description)
57    } else {
58        format!("[ReactCompiler] {}", error.reason)
59    };
60
61    DiagnosticMessage {
62        severity: Severity::Error,
63        message,
64        span: None,
65    }
66}
67
68fn error_detail_to_diagnostic(detail: &CompilerErrorDetailInfo, is_error: bool) -> DiagnosticMessage {
69    let message = if let Some(description) = &detail.description {
70        format!(
71            "[ReactCompiler] {}: {}. {}",
72            detail.category, detail.reason, description
73        )
74    } else {
75        format!("[ReactCompiler] {}: {}", detail.category, detail.reason)
76    };
77
78    DiagnosticMessage {
79        severity: if is_error {
80            Severity::Error
81        } else {
82            Severity::Warning
83        },
84        message,
85        span: None,
86    }
87}
88
89fn event_to_diagnostic(event: &LoggerEvent) -> Option<DiagnosticMessage> {
90    match event {
91        LoggerEvent::CompileSuccess { .. } => None,
92        LoggerEvent::CompileSkip { .. } => None,
93        LoggerEvent::CompileError { detail, .. }
94        | LoggerEvent::CompileErrorWithLoc { detail, .. } => {
95            Some(error_detail_to_diagnostic(detail, false))
96        }
97        LoggerEvent::CompileUnexpectedThrow { data, .. } => Some(DiagnosticMessage {
98            severity: Severity::Error,
99            message: format!("[ReactCompiler] Unexpected error: {}", data),
100            span: None,
101        }),
102        LoggerEvent::PipelineError { data, .. } => Some(DiagnosticMessage {
103            severity: Severity::Error,
104            message: format!("[ReactCompiler] Pipeline error: {}", data),
105            span: None,
106        }),
107    }
108}