diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2021-10-21 10:18:18 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-21 10:18:18 -0400 |
commit | 43cd0459b9ca383f18ca5b01b8c48e77737c3f1d (patch) | |
tree | 05eababf594247aaebc3d4f4f4a2a0f36415f2cb /cli/ast/mod.rs | |
parent | 299702161533d731db799f1bb6c7c95fd92c0c11 (diff) |
fix(lsp): formatting should error on certain additional swc diagnostics (#12491)
Diffstat (limited to 'cli/ast/mod.rs')
-rw-r--r-- | cli/ast/mod.rs | 187 |
1 files changed, 112 insertions, 75 deletions
diff --git a/cli/ast/mod.rs b/cli/ast/mod.rs index f0ad36885..894a42d4e 100644 --- a/cli/ast/mod.rs +++ b/cli/ast/mod.rs @@ -24,7 +24,7 @@ use deno_ast::swc::transforms::hygiene; use deno_ast::swc::transforms::pass::Optional; use deno_ast::swc::transforms::proposals; use deno_ast::swc::transforms::react; -use deno_ast::swc::transforms::resolver::ts_resolver; +use deno_ast::swc::transforms::resolver_with_mark; use deno_ast::swc::transforms::typescript; use deno_ast::swc::visit::FoldWith; use deno_ast::Diagnostic; @@ -182,6 +182,8 @@ fn strip_config_from_emit_options( options: &EmitOptions, ) -> typescript::strip::Config { typescript::strip::Config { + pragma: Some(options.jsx_factory.clone()), + pragma_frag: Some(options.jsx_fragment_factory.clone()), import_not_used_as_values: match options.imports_not_used_as_values { ImportsNotUsedAsValues::Remove => { typescript::strip::ImportsNotUsedAsValues::Remove @@ -219,42 +221,14 @@ pub fn transpile( let globals = Globals::new(); deno_ast::swc::common::GLOBALS.set(&globals, || { let top_level_mark = Mark::fresh(Mark::root()); - let jsx_pass = chain!( - ts_resolver(top_level_mark), - react::react( - source_map.clone(), - Some(&comments), - react::Options { - pragma: options.jsx_factory.clone(), - pragma_frag: options.jsx_fragment_factory.clone(), - // this will use `Object.assign()` instead of the `_extends` helper - // when spreading props. - use_builtins: true, - ..Default::default() - }, - top_level_mark, - ), - ); - let mut passes = chain!( - Optional::new(jsx_pass, options.transform_jsx), - Optional::new(transforms::DownlevelImportsFolder, options.repl_imports), - Optional::new(transforms::StripExportsFolder, options.repl_imports), - proposals::decorators::decorators(proposals::decorators::Config { - legacy: true, - emit_metadata: options.emit_metadata - }), - helpers::inject_helpers(), - typescript::strip::strip_with_config(strip_config_from_emit_options( - options - )), - fixer(Some(&comments)), - hygiene(), + let module = fold_program( + program, + options, + source_map.clone(), + &comments, + top_level_mark, ); - let program = helpers::HELPERS.set(&helpers::Helpers::new(false), || { - program.fold_with(&mut passes) - }); - let mut src_map_buf = vec![]; let mut buf = vec![]; { @@ -271,7 +245,7 @@ pub fn transpile( cm: source_map.clone(), wr: writer, }; - program.emit_with(&mut emitter)?; + module.emit_with(&mut emitter)?; } let mut src = String::from_utf8(buf)?; let mut map: Option<String> = None; @@ -299,8 +273,7 @@ pub fn transpile_module( specifier: &ModuleSpecifier, source: &str, media_type: MediaType, - emit_options: &EmitOptions, - globals: &Globals, + options: &EmitOptions, cm: Rc<SourceMap>, ) -> Result<(Rc<deno_ast::swc::common::SourceFile>, Module), AnyError> { let source = strip_bom(source); @@ -314,52 +287,85 @@ pub fn transpile_module( let module = parser.parse_module().map_err(|err| { let location = cm.lookup_char_pos(err.span().lo); Diagnostic { + specifier: specifier.to_string(), + span: err.span(), display_position: LineAndColumnDisplay { line_number: location.line, column_number: location.col_display + 1, }, - specifier: specifier.to_string(), - message: err.into_kind().msg().to_string(), + kind: err.into_kind(), } })?; - deno_ast::swc::common::GLOBALS.set(globals, || { - let top_level_mark = Mark::fresh(Mark::root()); - let jsx_pass = chain!( - ts_resolver(top_level_mark), - react::react( - cm, - Some(&comments), - react::Options { - pragma: emit_options.jsx_factory.clone(), - pragma_frag: emit_options.jsx_fragment_factory.clone(), - // this will use `Object.assign()` instead of the `_extends` helper - // when spreading props. - use_builtins: true, - ..Default::default() - }, - top_level_mark, - ), - ); - let mut passes = chain!( - Optional::new(jsx_pass, emit_options.transform_jsx), - proposals::decorators::decorators(proposals::decorators::Config { - legacy: true, - emit_metadata: emit_options.emit_metadata - }), - helpers::inject_helpers(), + let top_level_mark = Mark::fresh(Mark::root()); + let program = fold_program( + Program::Module(module), + options, + cm, + &comments, + top_level_mark, + ); + let module = match program { + Program::Module(module) => module, + _ => unreachable!(), + }; + + Ok((source_file, module)) +} + +fn fold_program( + program: Program, + options: &EmitOptions, + source_map: Rc<SourceMap>, + comments: &SingleThreadedComments, + top_level_mark: Mark, +) -> Program { + let jsx_pass = chain!( + resolver_with_mark(top_level_mark), + react::react( + source_map.clone(), + Some(comments), + react::Options { + pragma: options.jsx_factory.clone(), + pragma_frag: options.jsx_fragment_factory.clone(), + // this will use `Object.assign()` instead of the `_extends` helper + // when spreading props. + use_builtins: true, + ..Default::default() + }, + top_level_mark, + ), + ); + let mut passes = chain!( + Optional::new(transforms::DownlevelImportsFolder, options.repl_imports), + Optional::new(transforms::StripExportsFolder, options.repl_imports), + proposals::decorators::decorators(proposals::decorators::Config { + legacy: true, + emit_metadata: options.emit_metadata + }), + helpers::inject_helpers(), + Optional::new( typescript::strip::strip_with_config(strip_config_from_emit_options( - emit_options + options )), - fixer(Some(&comments)), - hygiene(), - ); - - let module = helpers::HELPERS.set(&helpers::Helpers::new(false), || { - module.fold_with(&mut passes) - }); - - Ok((source_file, module)) + !options.transform_jsx + ), + Optional::new( + typescript::strip::strip_with_jsx( + source_map, + strip_config_from_emit_options(options), + comments, + top_level_mark + ), + options.transform_jsx + ), + Optional::new(jsx_pass, options.transform_jsx), + fixer(Some(comments)), + hygiene(), + ); + + helpers::HELPERS.set(&helpers::Helpers::new(false), || { + program.fold_with(&mut passes) }) } @@ -435,6 +441,37 @@ mod tests { } #[test] + fn test_transpile_jsx_pragma() { + let specifier = resolve_url_or_path("https://deno.land/x/mod.ts") + .expect("could not resolve specifier"); + let source = r#" +/** @jsx h */ +/** @jsxFrag Fragment */ +import { h, Fragment } from "https://deno.land/x/mod.ts"; + +function App() { + return ( + <div><></></div> + ); +}"#; + let module = parse_module(ParseParams { + specifier: specifier.as_str().to_string(), + source: SourceTextInfo::from_string(source.to_string()), + media_type: deno_ast::MediaType::Jsx, + capture_tokens: false, + maybe_syntax: None, + scope_analysis: true, + }) + .unwrap(); + let (code, _) = transpile(&module, &EmitOptions::default()).unwrap(); + let expected = r#"/** @jsx h */ /** @jsxFrag Fragment */ import { h, Fragment } from "https://deno.land/x/mod.ts"; +function App() { + return(/*#__PURE__*/ h("div", null, /*#__PURE__*/ h(Fragment, null))); +}"#; + assert_eq!(&code[..expected.len()], expected); + } + + #[test] fn test_transpile_decorators() { let specifier = resolve_url_or_path("https://deno.land/x/mod.ts") .expect("could not resolve specifier"); |