diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index d025d35a8d5e46..c859abc0244ebf 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use base64::Engine; use deno_ast::MediaType; use deno_config::workspace::WorkspaceDirectory; use deno_config::workspace::WorkspaceDiscoverOptions; @@ -968,16 +967,27 @@ impl Inner { (|| { let compiler_options = config_file.to_compiler_options().ok()?.options; let jsx_import_source = compiler_options.get("jsxImportSource")?; - let jsx_import_source = jsx_import_source.as_str()?; + let jsx_import_source = jsx_import_source.as_str()?.to_string(); let referrer = config_file.specifier.clone(); - let specifier = Url::parse(&format!( - "data:application/typescript;base64,{}", - base64::engine::general_purpose::STANDARD - .encode(format!("import '{jsx_import_source}/jsx-runtime';")) - )) - .unwrap(); + let specifier = format!("{jsx_import_source}/jsx-runtime"); self.task_queue.queue_task(Box::new(|ls: LanguageServer| { spawn(async move { + let specifier = { + let inner = ls.inner.read().await; + let resolver = inner.resolver.as_graph_resolver(Some(&referrer)); + let Ok(specifier) = resolver.resolve( + &specifier, + &deno_graph::Range { + specifier: referrer.clone(), + start: deno_graph::Position::zeroed(), + end: deno_graph::Position::zeroed(), + }, + deno_graph::source::ResolutionMode::Types, + ) else { + return; + }; + specifier + }; if let Err(err) = ls.cache(vec![specifier], referrer, false).await { lsp_warn!("{:#}", err); } diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index b6cc71ec620dec..77d4915687a826 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -11698,27 +11698,111 @@ fn lsp_jsx_import_source_config_file_automatic_cache() { // The caching is done on an asynchronous task spawned after init, so there's // a chance it wasn't done in time and we need to wait for another batch of // diagnostics. + let mut version = 1; while !diagnostics.all().is_empty() { std::thread::sleep(std::time::Duration::from_millis(50)); // The post-cache diagnostics update triggers inconsistently on CI for some // reason. Force it with this notification. - diagnostics = client.did_open(json!({ - "textDocument": { - "uri": temp_dir.url().join("file.tsx").unwrap(), - "languageId": "typescriptreact", - "version": 1, - "text": " - export function Foo() { - return
; - } - ", - }, - })); + version += 1; + client.write_notification( + "textDocument/didChange", + json!({ + "textDocument": { + "uri": temp_dir.url().join("file.tsx").unwrap(), + "version": version, + }, + "contentChanges": [ + { + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 }, + }, + "text": "", + }, + ], + }), + ); + diagnostics = client.read_diagnostics(); } assert_eq!(diagnostics.all(), vec![]); client.shutdown(); } +#[ignore = "https://github.com/denoland/deno/issues/21770"] +#[test] +fn lsp_jsx_import_source_package_json_automatic_cache() { + let context = TestContextBuilder::new() + .use_http_server() + .use_temp_cwd() + .build(); + let temp_dir = context.temp_dir(); + temp_dir.write( + "deno.json", + json!({ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "preact", + }, + "nodeModulesDir": false, + }) + .to_string(), + ); + temp_dir.write( + "package.json", + json!({ + "dependencies": { + "preact": "^10.19.6", + }, + }) + .to_string(), + ); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); + let mut diagnostics = client.did_open(json!({ + "textDocument": { + "uri": temp_dir.url().join("file.tsx").unwrap(), + "languageId": "typescriptreact", + "version": 1, + "text": " + export function Foo() { + return
; + } + ", + }, + })); + // The caching is done on an asynchronous task spawned after init, so there's + // a chance it wasn't done in time and we need to wait for another batch of + // diagnostics. + let mut version = 1; + while !diagnostics.all().is_empty() { + std::thread::sleep(std::time::Duration::from_millis(50)); + // The post-cache diagnostics update triggers inconsistently on CI for some + // reason. Force it with this notification. + version += 1; + client.write_notification( + "textDocument/didChange", + json!({ + "textDocument": { + "uri": temp_dir.url().join("file.tsx").unwrap(), + "version": version, + }, + "contentChanges": [ + { + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 }, + }, + "text": "", + }, + ], + }), + ); + diagnostics = client.read_diagnostics(); + } + assert_eq!(json!(diagnostics.all()), json!([])); + client.shutdown(); +} + #[test] fn lsp_jsx_import_source_byonm_preact() { let context = TestContextBuilder::new()