Skip to content

Commit c22ff19

Browse files
authored
fix(lsp): resolve jsx import source with types mode (#25064)
1 parent 1d41692 commit c22ff19

File tree

5 files changed

+91
-30
lines changed

5 files changed

+91
-30
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ deno_config = { version = "=0.30.1", features = ["workspace", "sync"] }
6969
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
7070
deno_doc = { version = "0.146.0", features = ["html", "syntect"] }
7171
deno_emit = "=0.44.0"
72-
deno_graph = { version = "=0.81.2" }
72+
deno_graph = { version = "=0.81.3" }
7373
deno_lint = { version = "=0.63.1", features = ["docs"] }
7474
deno_lockfile.workspace = true
7575
deno_npm = "=0.23.1"

cli/lsp/language_server.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -956,31 +956,27 @@ impl Inner {
956956
.refresh(&self.config.settings, &self.workspace_files, &file_fetcher)
957957
.await;
958958
for config_file in self.config.tree.config_files() {
959-
if let Ok((compiler_options, _)) = config_file.to_compiler_options() {
960-
if let Some(compiler_options_obj) = compiler_options.as_object() {
961-
if let Some(jsx_import_source) =
962-
compiler_options_obj.get("jsxImportSource")
963-
{
964-
if let Some(jsx_import_source) = jsx_import_source.as_str() {
965-
let specifiers = vec![Url::parse(&format!(
966-
"data:application/typescript;base64,{}",
967-
base64::engine::general_purpose::STANDARD
968-
.encode(format!("import '{jsx_import_source}/jsx-runtime';"))
969-
))
970-
.unwrap()];
971-
let referrer = config_file.specifier.clone();
972-
self.task_queue.queue_task(Box::new(|ls: LanguageServer| {
973-
spawn(async move {
974-
if let Err(err) = ls.cache(specifiers, referrer, false).await
975-
{
976-
lsp_warn!("{:#}", err);
977-
}
978-
});
979-
}));
959+
(|| {
960+
let compiler_options = config_file.to_compiler_options().ok()?.0;
961+
let compiler_options_obj = compiler_options.as_object()?;
962+
let jsx_import_source = compiler_options_obj.get("jsxImportSource")?;
963+
let jsx_import_source = jsx_import_source.as_str()?;
964+
let referrer = config_file.specifier.clone();
965+
let specifier = Url::parse(&format!(
966+
"data:application/typescript;base64,{}",
967+
base64::engine::general_purpose::STANDARD
968+
.encode(format!("import '{jsx_import_source}/jsx-runtime';"))
969+
))
970+
.unwrap();
971+
self.task_queue.queue_task(Box::new(|ls: LanguageServer| {
972+
spawn(async move {
973+
if let Err(err) = ls.cache(vec![specifier], referrer, false).await {
974+
lsp_warn!("{:#}", err);
980975
}
981-
}
982-
}
983-
}
976+
});
977+
}));
978+
Some(())
979+
})();
984980
}
985981
}
986982

@@ -3533,19 +3529,22 @@ impl Inner {
35333529
force_global_cache: bool,
35343530
) -> Result<PrepareCacheResult, AnyError> {
35353531
let config_data = self.config.tree.data_for_specifier(&referrer);
3532+
let byonm = config_data.map(|d| d.byonm).unwrap_or(false);
35363533
let mut roots = if !specifiers.is_empty() {
35373534
specifiers
35383535
} else {
35393536
vec![referrer.clone()]
35403537
};
35413538

3542-
// always include the npm packages since resolution of one npm package
3543-
// might affect the resolution of other npm packages
3544-
if let Some(npm_reqs) = self
3539+
if byonm {
3540+
roots.retain(|s| s.scheme() != "npm");
3541+
} else if let Some(npm_reqs) = self
35453542
.documents
35463543
.npm_reqs_by_scope()
35473544
.get(&config_data.map(|d| d.scope.as_ref().clone()))
35483545
{
3546+
// always include the npm packages since resolution of one npm package
3547+
// might affect the resolution of other npm packages
35493548
roots.extend(
35503549
npm_reqs
35513550
.iter()

tests/integration/lsp_tests.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11724,6 +11724,66 @@ fn lsp_jsx_import_source_config_file_automatic_cache() {
1172411724
client.shutdown();
1172511725
}
1172611726

11727+
#[test]
11728+
fn lsp_jsx_import_source_byonm_preact() {
11729+
let context = TestContextBuilder::new()
11730+
.use_http_server()
11731+
.use_temp_cwd()
11732+
.add_npm_env_vars()
11733+
.build();
11734+
let temp_dir = context.temp_dir();
11735+
temp_dir.write(
11736+
"deno.json",
11737+
json!({
11738+
"compilerOptions": {
11739+
"jsx": "react-jsx",
11740+
"jsxImportSource": "npm:preact@^10.19.6"
11741+
},
11742+
"unstable": ["byonm"],
11743+
})
11744+
.to_string(),
11745+
);
11746+
temp_dir.write(
11747+
"package.json",
11748+
json!({
11749+
"dependencies": {
11750+
"preact": "^10.19.6",
11751+
},
11752+
})
11753+
.to_string(),
11754+
);
11755+
let file = source_file(temp_dir.path().join("file.tsx"), r#"<div></div>;"#);
11756+
context.run_npm("install");
11757+
let mut client = context.new_lsp_command().build();
11758+
client.initialize_default();
11759+
let diagnostics = client.did_open_file(&file);
11760+
assert_eq!(json!(diagnostics.all()), json!([]));
11761+
let res = client.write_request(
11762+
"textDocument/hover",
11763+
json!({
11764+
"textDocument": { "uri": file.uri() },
11765+
"position": { "line": 0, "character": 1 },
11766+
}),
11767+
);
11768+
assert_eq!(
11769+
res,
11770+
json!({
11771+
"contents": [
11772+
{
11773+
"language": "typescript",
11774+
"value": "(property) JSXInternal.IntrinsicElements.div: JSXInternal.HTMLAttributes<HTMLDivElement>",
11775+
},
11776+
"",
11777+
],
11778+
"range": {
11779+
"start": { "line": 0, "character": 1 },
11780+
"end": { "line": 0, "character": 4 },
11781+
},
11782+
}),
11783+
);
11784+
client.shutdown();
11785+
}
11786+
1172711787
#[test]
1172811788
fn lsp_jsx_import_source_types_pragma() {
1172911789
let context = TestContextBuilder::new()

tests/util/server/src/lsp.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,8 @@ impl SourceFile {
13011301
let lang = match path.as_path().extension().unwrap().to_str().unwrap() {
13021302
"js" => "javascript",
13031303
"ts" | "d.ts" => "typescript",
1304+
"jsx" => "javascriptreact",
1305+
"tsx" => "typescriptreact",
13041306
"json" => "json",
13051307
"md" => "markdown",
13061308
other => panic!("unsupported file extension: {other}"),

0 commit comments

Comments
 (0)