From ebb7fe412e97e851a9373be71931f13930e7a02e Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Mon, 16 Oct 2023 20:21:57 +0100 Subject: [PATCH] fix(lsp): show diagnostics for untitled files (#20916) --- cli/lsp/completions.rs | 4 +-- cli/lsp/documents.rs | 31 +++++++++++++-------- cli/lsp/tsc.rs | 11 ++++---- cli/tests/integration/lsp_tests.rs | 43 ++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs index c6fc6216e8b452..08f8dbf81e7884 100644 --- a/cli/lsp/completions.rs +++ b/cli/lsp/completions.rs @@ -2,7 +2,7 @@ use super::client::Client; use super::config::ConfigSnapshot; -use super::documents::cell_to_file_specifier; +use super::documents::file_like_to_file_specifier; use super::documents::Documents; use super::documents::DocumentsFilter; use super::lsp_custom; @@ -365,7 +365,7 @@ fn get_local_completions( current: &str, range: &lsp::Range, ) -> Option> { - let base = match cell_to_file_specifier(base) { + let base = match file_like_to_file_specifier(base) { Some(s) => s, None => base.clone(), }; diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 748b5b11ccdc51..f017989b4259bf 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -89,12 +89,13 @@ static TSX_HEADERS: Lazy> = Lazy::new(|| { .collect() }); -pub const DOCUMENT_SCHEMES: [&str; 6] = [ +pub const DOCUMENT_SCHEMES: [&str; 7] = [ "data", "blob", "file", "http", "https", + "untitled", "deno-notebook-cell", ]; @@ -259,22 +260,24 @@ impl AssetOrDocument { } } -/// Convert a `deno-notebook-cell:` specifier to a `file:` specifier. +/// Convert a e.g. `deno-notebook-cell:` specifier to a `file:` specifier. /// ```rust /// assert_eq!( -/// cell_to_file_specifier( +/// file_like_to_file_specifier( /// &Url::parse("deno-notebook-cell:/path/to/file.ipynb#abc").unwrap(), /// ), /// Some(Url::parse("file:///path/to/file.ipynb#abc").unwrap()), /// ); -pub fn cell_to_file_specifier(specifier: &Url) -> Option { - if specifier.scheme() == "deno-notebook-cell" { - if let Ok(specifier) = ModuleSpecifier::parse(&format!( +pub fn file_like_to_file_specifier(specifier: &Url) -> Option { + if matches!(specifier.scheme(), "untitled" | "deno-notebook-cell") { + if let Ok(mut s) = ModuleSpecifier::parse(&format!( "file://{}", &specifier.as_str() [url::quirks::internal_components(specifier).host_end as usize..], )) { - return Some(specifier); + s.query_pairs_mut() + .append_pair("scheme", specifier.scheme()); + return Some(s); } } None @@ -300,22 +303,28 @@ impl DocumentDependencies { deps: module.dependencies.clone(), maybe_types_dependency: module.maybe_types_dependency.clone(), }; - if module.specifier.scheme() == "deno-notebook-cell" { + if file_like_to_file_specifier(&module.specifier).is_some() { for (_, dep) in &mut deps.deps { if let Resolution::Ok(resolved) = &mut dep.maybe_code { - if let Some(specifier) = cell_to_file_specifier(&resolved.specifier) { + if let Some(specifier) = + file_like_to_file_specifier(&resolved.specifier) + { resolved.specifier = specifier; } } if let Resolution::Ok(resolved) = &mut dep.maybe_type { - if let Some(specifier) = cell_to_file_specifier(&resolved.specifier) { + if let Some(specifier) = + file_like_to_file_specifier(&resolved.specifier) + { resolved.specifier = specifier; } } } if let Some(dep) = &mut deps.maybe_types_dependency { if let Resolution::Ok(resolved) = &mut dep.dependency { - if let Some(specifier) = cell_to_file_specifier(&resolved.specifier) { + if let Some(specifier) = + file_like_to_file_specifier(&resolved.specifier) + { resolved.specifier = specifier; } } diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index bac3f837746fb4..da6b229c8b1bc9 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -3,7 +3,7 @@ use super::analysis::CodeActionData; use super::code_lens; use super::config; -use super::documents::cell_to_file_specifier; +use super::documents::file_like_to_file_specifier; use super::documents::AssetOrDocument; use super::documents::DocumentsFilter; use super::language_server; @@ -3664,11 +3664,12 @@ impl TscSpecifierMap { if let Some(specifier) = self.denormalized_specifiers.get(original) { return specifier.to_string(); } - let mut specifier = original.to_string(); + let mut specifier = if let Some(s) = file_like_to_file_specifier(original) { + s.to_string() + } else { + original.to_string() + }; let media_type = if original.scheme() == "deno-notebook-cell" { - if let Some(s) = cell_to_file_specifier(original) { - specifier = s.to_string(); - } MediaType::TypeScript } else { MediaType::from_specifier(original) diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 5f76d3de2034ab..50b01b2ea4f56b 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -8041,6 +8041,49 @@ fn lsp_jupyter_diagnostics() { client.shutdown(); } +#[test] +fn lsp_untitled_file_diagnostics() { + let context = TestContextBuilder::new().use_temp_cwd().build(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); + let diagnostics = client.did_open(json!({ + "textDocument": { + "uri": "untitled:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "Deno.readTextFileSync(1234);", + }, + })); + assert_eq!( + json!(diagnostics.all_messages()), + json!([ + { + "uri": "untitled:///a/file.ts", + "diagnostics": [ + { + "range": { + "start": { + "line": 0, + "character": 22, + }, + "end": { + "line": 0, + "character": 26, + }, + }, + "severity": 1, + "code": 2345, + "source": "deno-ts", + "message": "Argument of type 'number' is not assignable to parameter of type 'string | URL'.", + }, + ], + "version": 1, + }, + ]) + ); + client.shutdown(); +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PerformanceAverage {