diff options
Diffstat (limited to 'cli/lsp/completions.rs')
-rw-r--r-- | cli/lsp/completions.rs | 120 |
1 files changed, 93 insertions, 27 deletions
diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs index 56abeb9d2..95a13d59a 100644 --- a/cli/lsp/completions.rs +++ b/cli/lsp/completions.rs @@ -2,6 +2,7 @@ use super::analysis; use super::language_server; +use super::lsp_custom; use super::tsc; use crate::fs_util::is_supported_ext; @@ -9,6 +10,7 @@ use crate::media_type::MediaType; use deno_core::normalize_path; use deno_core::resolve_path; +use deno_core::resolve_url; use deno_core::serde::Deserialize; use deno_core::serde::Serialize; use deno_core::url::Position; @@ -34,6 +36,64 @@ pub struct CompletionItemData { pub tsc: Option<tsc::CompletionItemData>, } +/// Check if the origin can be auto-configured for completions, and if so, send +/// a notification to the client. +async fn check_auto_config_registry( + url_str: &str, + snapshot: &language_server::StateSnapshot, + client: lspower::Client, +) { + // check to see if auto discovery is enabled + if snapshot + .config + .settings + .workspace + .suggest + .imports + .auto_discover + { + if let Ok(specifier) = resolve_url(url_str) { + let scheme = specifier.scheme(); + let path = &specifier[Position::BeforePath..]; + if scheme.starts_with("http") + && !path.is_empty() + && url_str.ends_with(path) + { + // check to see if this origin is already explicitly set + let in_config = snapshot + .config + .settings + .workspace + .suggest + .imports + .hosts + .iter() + .any(|(h, _)| { + resolve_url(h).map(|u| u.origin()) == Ok(specifier.origin()) + }); + // if it isn't in the configuration, we will check to see if it supports + // suggestions and send a notification to the client. + if !in_config { + let origin = specifier.origin().ascii_serialization(); + let suggestions = snapshot + .module_registries + .fetch_config(&origin) + .await + .is_ok(); + client + .send_custom_notification::<lsp_custom::RegistryStateNotification>( + lsp_custom::RegistryStateNotificationParams { + origin, + suggestions, + }, + ) + .await; + } + } + } + } +} + /// Given a specifier, a position, and a snapshot, optionally return a /// completion response, which will be valid import completions for the specific /// context. @@ -41,6 +101,7 @@ pub async fn get_import_completions( specifier: &ModuleSpecifier, position: &lsp::Position, state_snapshot: &language_server::StateSnapshot, + client: lspower::Client, ) -> Option<lsp::CompletionResponse> { if let Ok(Some(source)) = state_snapshot.documents.content(specifier) { let media_type = MediaType::from(specifier); @@ -58,6 +119,8 @@ pub async fn get_import_completions( } // completion of modules from a module registry or cache if !current_specifier.is_empty() { + check_auto_config_registry(¤t_specifier, state_snapshot, client) + .await; let offset = if position.character > range.start.character { (position.character - range.start.character) as usize } else { @@ -808,11 +871,17 @@ mod tests { } #[tokio::test] - async fn test_get_import_completions() { + async fn test_get_workspace_completions() { let specifier = resolve_url("file:///a/b/c.ts").unwrap(); - let position = lsp::Position { - line: 0, - character: 21, + let range = lsp::Range { + start: lsp::Position { + line: 0, + character: 20, + }, + end: lsp::Position { + line: 0, + character: 21, + }, }; let state_snapshot = setup( &[ @@ -822,32 +891,29 @@ mod tests { &[("https://deno.land/x/a/b/c.ts", "console.log(1);\n")], ); let actual = - get_import_completions(&specifier, &position, &state_snapshot).await; + get_workspace_completions(&specifier, "h", &range, &state_snapshot); assert_eq!( actual, - Some(lsp::CompletionResponse::List(lsp::CompletionList { - is_incomplete: false, - items: vec![lsp::CompletionItem { - label: "https://deno.land/x/a/b/c.ts".to_string(), - kind: Some(lsp::CompletionItemKind::File), - detail: Some("(remote)".to_string()), - sort_text: Some("1".to_string()), - text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { - range: lsp::Range { - start: lsp::Position { - line: 0, - character: 20 - }, - end: lsp::Position { - line: 0, - character: 21, - } + vec![lsp::CompletionItem { + label: "https://deno.land/x/a/b/c.ts".to_string(), + kind: Some(lsp::CompletionItemKind::File), + detail: Some("(remote)".to_string()), + sort_text: Some("1".to_string()), + text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { + range: lsp::Range { + start: lsp::Position { + line: 0, + character: 20 }, - new_text: "https://deno.land/x/a/b/c.ts".to_string(), - })), - ..Default::default() - }] - })) + end: lsp::Position { + line: 0, + character: 21, + } + }, + new_text: "https://deno.land/x/a/b/c.ts".to_string(), + })), + ..Default::default() + }] ); } } |