diff --git a/apps/oxfmt/src/service.rs b/apps/oxfmt/src/service.rs index 6203580db3e53..9654cbec8bbf1 100644 --- a/apps/oxfmt/src/service.rs +++ b/apps/oxfmt/src/service.rs @@ -5,7 +5,7 @@ use rayon::prelude::*; use oxc_allocator::Allocator; use oxc_diagnostics::{DiagnosticSender, DiagnosticService, OxcDiagnostic}; -use oxc_formatter::{FormatOptions, Formatter}; +use oxc_formatter::{FormatOptions, Formatter, enable_jsx_source_type}; use oxc_parser::{ParseOptions, Parser}; use crate::{command::OutputOptions, walk::WalkEntry}; @@ -45,7 +45,7 @@ impl FormatService { let start_time = Instant::now(); let path = Path::new(&entry.path); - let source_type = entry.source_type; + let source_type = enable_jsx_source_type(entry.source_type); // TODO: Use `read_to_arena_str()` like `oxlint`? let source_text = fs::read_to_string(path).expect("Failed to read file"); diff --git a/crates/oxc_formatter/src/lib.rs b/crates/oxc_formatter/src/lib.rs index cf1c810f53651..7382c8078a037 100644 --- a/crates/oxc_formatter/src/lib.rs +++ b/crates/oxc_formatter/src/lib.rs @@ -35,7 +35,10 @@ use rustc_hash::{FxHashMap, FxHashSet}; use write::FormatWrite; pub use crate::options::*; -pub use crate::service::{oxfmtrc::Oxfmtrc, source_type::get_supported_source_type}; +pub use crate::service::{ + oxfmtrc::Oxfmtrc, + source_type::{enable_jsx_source_type, get_supported_source_type}, +}; use crate::{ formatter::{FormatContext, Formatted, format_element::document::Document}, generated::ast_nodes::{AstNode, AstNodes}, diff --git a/crates/oxc_formatter/src/service/source_type.rs b/crates/oxc_formatter/src/service/source_type.rs index 5c0617ec95460..9874801d1c717 100644 --- a/crates/oxc_formatter/src/service/source_type.rs +++ b/crates/oxc_formatter/src/service/source_type.rs @@ -48,3 +48,23 @@ pub fn get_supported_source_type(path: &std::path::Path) -> Option { None } + +#[must_use] +pub fn enable_jsx_source_type(source_type: SourceType) -> SourceType { + if source_type.is_jsx() { + return source_type; + } + + // Always enable JSX for JavaScript files, no syntax conflict + if source_type.is_javascript() { + return source_type.with_jsx(true); + } + + // Prettier uses `regexp.test(source_text)` to detect JSX in TypeScript files. + // But we don't follow it for now, since it hurts the performance. + // if source_type.is_typescript() { + // // See https://github.com/prettier/prettier/blob/0d1e7abd5037a1fe8fbcf88a4d8cd13ec4d13a78/src/language-js/parse/utils/jsx-regexp.evaluate.js + // } + + source_type +} diff --git a/crates/oxc_language_server/src/formatter/server_formatter.rs b/crates/oxc_language_server/src/formatter/server_formatter.rs index 29a474e119c7d..69a8794ffa66d 100644 --- a/crates/oxc_language_server/src/formatter/server_formatter.rs +++ b/crates/oxc_language_server/src/formatter/server_formatter.rs @@ -3,7 +3,9 @@ use std::path::Path; use log::warn; use oxc_allocator::Allocator; use oxc_data_structures::rope::{Rope, get_line_column}; -use oxc_formatter::{FormatOptions, Formatter, Oxfmtrc, get_supported_source_type}; +use oxc_formatter::{ + FormatOptions, Formatter, Oxfmtrc, enable_jsx_source_type, get_supported_source_type, +}; use oxc_parser::{ParseOptions, Parser}; use tower_lsp_server::{ UriExt, @@ -25,7 +27,7 @@ impl ServerFormatter { pub fn run_single(&self, uri: &Uri, content: Option) -> Option> { let path = uri.to_file_path()?; - let source_type = get_supported_source_type(&path)?; + let source_type = get_supported_source_type(&path).map(enable_jsx_source_type)?; let source_text = if let Some(content) = content { content } else {