use std::{cell::RefCell, collections::HashSet};
use oxc_span::Span;
use oxc_diagnostics::OxcDiagnostic;
use vue_compiler_core::error::{CompilationError, CompilationErrorKind, ErrorHandler};
use crate::parser::parse::SourceLocatonSpan;
pub struct OxcErrorHandler<'a> {
errors: &'a RefCell<&'a mut Vec<OxcDiagnostic>>,
panicked: &'a RefCell<bool>,
}
impl<'a> OxcErrorHandler<'a> {
pub const fn new(
errors: &'a RefCell<&'a mut Vec<OxcDiagnostic>>,
panicked: &'a RefCell<bool>,
) -> Self {
Self { errors, panicked }
}
}
impl ErrorHandler for OxcErrorHandler<'_> {
fn on_error(&self, error: CompilationError) {
if should_panic(&error) {
*self.panicked.borrow_mut() = true;
}
if !is_warn(&error) {
self
.errors
.borrow_mut()
.push(OxcDiagnostic::error(error.to_string()).with_label(error.location.span()));
}
}
}
#[must_use]
const fn is_warn(error: &CompilationError) -> bool {
matches!(
error.kind,
CompilationErrorKind::InvalidFirstCharacterOfTagName
| CompilationErrorKind::NestedComment
| CompilationErrorKind::IncorrectlyClosedComment
| CompilationErrorKind::IncorrectlyOpenedComment
| CompilationErrorKind::AbruptClosingOfEmptyComment
| CompilationErrorKind::MissingWhitespaceBetweenAttributes
| CompilationErrorKind::MissingDirectiveArg
)
}
#[must_use]
const fn should_panic(error: &CompilationError) -> bool {
matches!(
error.kind,
CompilationErrorKind::EofInTag
| CompilationErrorKind::EofInComment
| CompilationErrorKind::EofInCdata
| CompilationErrorKind::EofBeforeTagName
| CompilationErrorKind::EofInScriptHtmlCommentLikeText
| CompilationErrorKind::MissingInterpolationEnd
| CompilationErrorKind::MissingDynamicDirectiveArgumentEnd
| CompilationErrorKind::MissingEndTag
| CompilationErrorKind::UnexpectedNullCharacter
| CompilationErrorKind::CDataInHtmlContent
)
}
#[cold]
pub fn unexpected_script_lang(errors: &mut Vec<OxcDiagnostic>, lang: &str) {
errors.push(OxcDiagnostic::error(format!("Unsupported script language: {lang}")));
}
#[cold]
pub fn multiple_script_tags(errors: &mut Vec<OxcDiagnostic>, source_types: &HashSet<&str>) {
errors.push(OxcDiagnostic::error(format!(
"Multiple script tags with different languages: {source_types:?}"
)));
}
#[cold]
pub fn v_else_without_adjacent_if(errors: &mut Vec<OxcDiagnostic>, span: Span) {
errors.push(
OxcDiagnostic::error("v-else/v-else-if has no adjacent v-if or v-else-if.").with_label(span),
);
}
#[cold]
pub fn export_default_must_be_expression(errors: &mut Vec<OxcDiagnostic>, span: Span) {
errors.push(
OxcDiagnostic::error("Vue SFC export default must be an expression.")
.with_help("Use `export default { ... }` (options object) instead of declarations.")
.with_label(span),
);
}
#[cold]
pub fn invalid_v_for_expression(errors: &mut Vec<OxcDiagnostic>, span: Span) {
errors.push(OxcDiagnostic::error("Invalid v-for expression").with_label(span));
}