diff --git a/src/format_text.rs b/src/format_text.rs index da3e9e1..9b386d8 100644 --- a/src/format_text.rs +++ b/src/format_text.rs @@ -35,18 +35,18 @@ use super::swc::parse_swc_ast; /// // now format many files (it is recommended to parallelize this) /// let files_to_format = vec![(PathBuf::from("path/to/file.ts"), "const t = 5 ;")]; /// for (file_path, file_text) in files_to_format { -/// let result = format_text(&file_path, file_text.into(), &config); +/// let result = format_text(&file_path, None, file_text.into(), &config); /// // save result here... /// } /// ``` -pub fn format_text(file_path: &Path, file_text: String, config: &Configuration) -> Result> { +pub fn format_text(file_path: &Path, file_extension: Option<&str>, file_text: String, config: &Configuration) -> Result> { if super::utils::file_text_has_ignore_comment(&file_text, &config.ignore_file_comment_text) { Ok(None) } else { let had_bom = file_text.starts_with("\u{FEFF}"); let file_text = if had_bom { file_text[3..].to_string() } else { file_text }; let file_text: Arc = file_text.into(); - let parsed_source = parse_swc_ast(file_path, file_text)?; + let parsed_source = parse_swc_ast(file_path, file_extension, file_text)?; match inner_format(&parsed_source, config)? { Some(new_text) => Ok(Some(new_text)), None => { @@ -89,7 +89,7 @@ fn inner_format(parsed_source: &ParsedSource, config: &Configuration) -> Result< #[cfg(feature = "tracing")] pub fn trace_file(file_path: &Path, file_text: &str, config: &Configuration) -> dprint_core::formatting::TracingResult { - let parsed_source = parse_swc_ast(file_path, file_text.into()).unwrap(); + let parsed_source = parse_swc_ast(file_path, None, file_text.into()).unwrap(); ensure_no_specific_syntax_errors(&parsed_source).unwrap(); dprint_core::formatting::trace_printing(|| generate(&parsed_source, config), config_to_print_options(file_text, config)) } @@ -111,7 +111,7 @@ mod test { fn strips_bom() { for input_text in ["\u{FEFF}const t = 5;\n", "\u{FEFF}const t = 5;"] { let config = crate::configuration::ConfigurationBuilder::new().build(); - let result = format_text(&std::path::PathBuf::from("test.ts"), input_text.into(), &config).unwrap().unwrap(); + let result = format_text(&std::path::PathBuf::from("test.ts"), None, input_text.into(), &config).unwrap().unwrap(); assert_eq!(result, "const t = 5;\n"); } } diff --git a/src/swc.rs b/src/swc.rs index f7a4728..0401f16 100644 --- a/src/swc.rs +++ b/src/swc.rs @@ -8,18 +8,18 @@ use deno_ast::ParsedSource; use std::path::Path; use std::sync::Arc; -pub fn parse_swc_ast(file_path: &Path, file_text: Arc) -> Result { - match parse_inner(file_path, file_text.clone()) { +pub fn parse_swc_ast(file_path: &Path, file_extension: Option<&str>, file_text: Arc) -> Result { + match parse_inner(file_path, file_extension, file_text.clone()) { Ok(result) => Ok(result), Err(err) => { - let lowercase_ext = get_lowercase_extension(file_path); + let lowercase_ext = file_extension.map(|ext| ext.to_string()).or_else(|| get_lowercase_extension(file_path)); let new_file_path = match lowercase_ext.as_deref() { Some("ts") | Some("cts") | Some("mts") => file_path.with_extension("tsx"), Some("js") | Some("cjs") | Some("mjs") => file_path.with_extension("jsx"), _ => return Err(err), }; // try to parse as jsx - match parse_inner(&new_file_path, file_text) { + match parse_inner(&new_file_path, None, file_text) { Ok(result) => Ok(result), Err(_) => Err(err), // return the original error } @@ -27,14 +27,19 @@ pub fn parse_swc_ast(file_path: &Path, file_text: Arc) -> Result) -> Result { - let parsed_source = parse_inner_no_diagnostic_check(file_path, text)?; +fn parse_inner(file_path: &Path, file_extension: Option<&str>, text: Arc) -> Result { + let parsed_source = parse_inner_no_diagnostic_check(file_path, file_extension, text)?; ensure_no_specific_syntax_errors(&parsed_source)?; Ok(parsed_source) } -fn parse_inner_no_diagnostic_check(file_path: &Path, text: Arc) -> Result { - let media_type = deno_ast::MediaType::from_path(file_path); +fn parse_inner_no_diagnostic_check(file_path: &Path, file_extension: Option<&str>, text: Arc) -> Result { + let media_type = if let Some(file_extension) = file_extension { + deno_ast::MediaType::from_path(&file_path.with_extension(file_extension)) + } else { + deno_ast::MediaType::from_path(file_path) + }; + let mut syntax = deno_ast::get_syntax(media_type); if let Syntax::Es(es) = &mut syntax { // support decorators in js @@ -260,7 +265,7 @@ mod tests { fn run_fatal_diagnostic_test(file_path: &str, text: &str, expected: &str) { let file_path = PathBuf::from(file_path); - assert_eq!(parse_swc_ast(&file_path, text.into()).err().unwrap().to_string(), expected); + assert_eq!(parse_swc_ast(&file_path, None, text.into()).err().unwrap().to_string(), expected); } #[test] @@ -286,6 +291,12 @@ mod tests { ); } + #[test] + fn file_extension_overwrite() { + let file_path = PathBuf::from("./test.js"); + assert!(parse_swc_ast(&file_path, Some("ts"), "const foo: string = 'bar';".into()).is_ok()); + } + #[test] fn it_should_error_for_exected_close_brace() { // swc can parse this, but we explicitly fail formatting @@ -342,11 +353,11 @@ Merge conflict marker encountered. at file:///test.ts:6:1 fn run_non_fatal_diagnostic_test(file_path: &str, text: &str, expected: &str) { let file_path = PathBuf::from(file_path); - assert_eq!(format!("{}", parse_swc_ast(&file_path, text.into()).err().unwrap()), expected); + assert_eq!(format!("{}", parse_swc_ast(&file_path, None, text.into()).err().unwrap()), expected); // this error should also be surfaced in `format_parsed_source` if someone provides // a source file that had a non-fatal diagnostic - let parsed_source = parse_inner_no_diagnostic_check(&file_path, text.into()).unwrap(); + let parsed_source = parse_inner_no_diagnostic_check(&file_path, None, text.into()).unwrap(); let config = ConfigurationBuilder::new().build(); assert_eq!(crate::format_parsed_source(&parsed_source, &config).err().unwrap().to_string(), expected); } diff --git a/src/wasm_plugin.rs b/src/wasm_plugin.rs index a6a4296..69b7d14 100644 --- a/src/wasm_plugin.rs +++ b/src/wasm_plugin.rs @@ -58,7 +58,7 @@ impl SyncPluginHandler for TypeScriptPluginHandler { _format_with_host: impl FnMut(&Path, Vec, &ConfigKeyMap) -> FormatResult, ) -> FormatResult { let file_text = String::from_utf8(file_bytes)?; - super::format_text(file_path, file_text, config).map(|maybe_text| maybe_text.map(|t| t.into_bytes())) + super::format_text(file_path, None, file_text, config).map(|maybe_text| maybe_text.map(|t| t.into_bytes())) } } diff --git a/tests/spec_test.rs b/tests/spec_test.rs index a4a510c..c0c429c 100644 --- a/tests/spec_test.rs +++ b/tests/spec_test.rs @@ -28,7 +28,7 @@ fn main() { let config_result = resolve_config(spec_config, &global_config); ensure_no_diagnostics(&config_result.diagnostics); - format_text(file_name, file_text.into(), &config_result.config) + format_text(file_name, None, file_text.into(), &config_result.config) }) }, Arc::new(move |_file_name, _file_text, _spec_config| {