summaryrefslogtreecommitdiff
path: root/cli/lsp/completions.rs
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2024-02-29 03:54:16 +0000
committerGitHub <noreply@github.com>2024-02-29 03:54:16 +0000
commit3a43568481108545178f5dd2f928d40736dc987a (patch)
tree5c9deec7135b5c9ace35aa2c13b238b3fdb53bb1 /cli/lsp/completions.rs
parent814eb420608b21d3d79d3580317d2e803d240589 (diff)
feat(lsp): jsr specifier completions (#22612)
Diffstat (limited to 'cli/lsp/completions.rs')
-rw-r--r--cli/lsp/completions.rs639
1 files changed, 524 insertions, 115 deletions
diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs
index 7fe161039..074d913c5 100644
--- a/cli/lsp/completions.rs
+++ b/cli/lsp/completions.rs
@@ -5,10 +5,12 @@ use super::config::ConfigSnapshot;
use super::config::WorkspaceSettings;
use super::documents::Documents;
use super::documents::DocumentsFilter;
+use super::jsr::CliJsrSearchApi;
+use super::jsr::JsrResolver;
use super::lsp_custom;
use super::npm::CliNpmSearchApi;
-use super::npm::NpmSearchApi;
use super::registries::ModuleRegistry;
+use super::search::PackageSearchApi;
use super::tsc;
use crate::util::path::is_importable_ext;
@@ -25,6 +27,8 @@ use deno_core::serde::Serialize;
use deno_core::serde_json::json;
use deno_core::url::Position;
use deno_core::ModuleSpecifier;
+use deno_semver::jsr::JsrPackageReqReference;
+use deno_semver::package::PackageNv;
use import_map::ImportMap;
use once_cell::sync::Lazy;
use regex::Regex;
@@ -148,6 +152,7 @@ pub async fn get_import_completions(
config: &ConfigSnapshot,
client: &Client,
module_registries: &ModuleRegistry,
+ jsr_search_api: &CliJsrSearchApi,
npm_search_api: &CliNpmSearchApi,
documents: &Documents,
maybe_import_map: Option<Arc<ImportMap>>,
@@ -170,6 +175,19 @@ pub async fn get_import_completions(
is_incomplete: false,
items: get_local_completions(specifier, &text, &range)?,
}))
+ } else if text.starts_with("jsr:") {
+ let items = get_jsr_completions(
+ specifier,
+ &text,
+ &range,
+ jsr_search_api,
+ jsr_search_api.get_resolver(),
+ )
+ .await?;
+ Some(lsp::CompletionResponse::List(lsp::CompletionList {
+ is_incomplete: !items.is_empty(),
+ items,
+ }))
} else if text.starts_with("npm:") {
let items =
get_npm_completions(specifier, &text, &range, npm_search_api).await?;
@@ -475,8 +493,7 @@ fn get_relative_specifiers(
}
/// Find the index of the '@' delimiting the package name and version, if any.
-fn parse_npm_specifier_version_index(specifier: &str) -> Option<usize> {
- let bare_specifier = specifier.strip_prefix("npm:")?;
+fn parse_bare_specifier_version_index(bare_specifier: &str) -> Option<usize> {
if bare_specifier.starts_with('@') {
bare_specifier
.find('/')
@@ -486,49 +503,188 @@ fn parse_npm_specifier_version_index(specifier: &str) -> Option<usize> {
.find('@')
.filter(|idx2| !bare_specifier[idx..][1..*idx2].is_empty())
.filter(|idx2| !bare_specifier[idx..][1..*idx2].contains('/'))
- .map(|idx2| 4 + idx + idx2)
+ .map(|idx2| idx + idx2)
})
} else {
bare_specifier
.find('@')
.filter(|idx| !bare_specifier[1..*idx].is_empty())
.filter(|idx| !bare_specifier[1..*idx].contains('/'))
- .map(|idx| 4 + idx)
}
}
+async fn get_jsr_completions(
+ referrer: &ModuleSpecifier,
+ specifier: &str,
+ range: &lsp::Range,
+ jsr_search_api: &impl PackageSearchApi,
+ jsr_resolver: &JsrResolver,
+) -> Option<Vec<lsp::CompletionItem>> {
+ // First try to match `jsr:some-package@some-version/<export-to-complete>`.
+ if let Ok(req_ref) = JsrPackageReqReference::from_str(specifier) {
+ let sub_path = req_ref.sub_path();
+ if sub_path.is_some() || specifier.ends_with('/') {
+ let export_prefix = sub_path.unwrap_or("");
+ let req = req_ref.req();
+ let nv = jsr_resolver.req_to_nv(req);
+ let nv = nv.or_else(|| PackageNv::from_str(&req.to_string()).ok())?;
+ let exports = jsr_search_api.exports(&nv).await.ok()?;
+ let items = exports
+ .iter()
+ .enumerate()
+ .filter_map(|(idx, export)| {
+ if export == "." {
+ return None;
+ }
+ let export = export.strip_prefix("./").unwrap_or(export.as_str());
+ if !export.starts_with(export_prefix) {
+ return None;
+ }
+ let specifier = format!("jsr:{}/{}", req_ref.req(), export);
+ let command = Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!([&specifier]),
+ json!(referrer),
+ json!({ "forceGlobalCache": true }),
+ ]),
+ });
+ let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range: *range,
+ new_text: specifier.clone(),
+ }));
+ Some(lsp::CompletionItem {
+ label: specifier,
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some(format!("{:0>10}", idx + 1)),
+ text_edit,
+ command,
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
+ ),
+ ..Default::default()
+ })
+ })
+ .collect();
+ return Some(items);
+ }
+ }
+
+ // Then try to match `jsr:some-package@<version-to-complete>`.
+ let bare_specifier = specifier.strip_prefix("jsr:")?;
+ if let Some(v_index) = parse_bare_specifier_version_index(bare_specifier) {
+ let package_name = &bare_specifier[..v_index];
+ let v_prefix = &bare_specifier[(v_index + 1)..];
+
+ let versions = jsr_search_api.versions(package_name).await.ok()?;
+ let items = versions
+ .iter()
+ .enumerate()
+ .filter_map(|(idx, version)| {
+ let version = version.to_string();
+ if !version.starts_with(v_prefix) {
+ return None;
+ }
+ let specifier = format!("jsr:{}@{}", package_name, version);
+ let command = Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!([&specifier]),
+ json!(referrer),
+ json!({ "forceGlobalCache": true }),
+ ]),
+ });
+ let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range: *range,
+ new_text: specifier.clone(),
+ }));
+ Some(lsp::CompletionItem {
+ label: specifier,
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some(format!("{:0>10}", idx + 1)),
+ text_edit,
+ command,
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
+ ),
+ ..Default::default()
+ })
+ })
+ .collect();
+ return Some(items);
+ }
+
+ // Otherwise match `jsr:<package-to-complete>`.
+ let names = jsr_search_api.search(bare_specifier).await.ok()?;
+ let items = names
+ .iter()
+ .enumerate()
+ .map(|(idx, name)| {
+ let specifier = format!("jsr:{}", name);
+ let command = Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!([&specifier]),
+ json!(referrer),
+ json!({ "forceGlobalCache": true }),
+ ]),
+ });
+ let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range: *range,
+ new_text: specifier.clone(),
+ }));
+ lsp::CompletionItem {
+ label: specifier,
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some(format!("{:0>10}", idx + 1)),
+ text_edit,
+ command,
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
+ ),
+ ..Default::default()
+ }
+ })
+ .collect();
+ Some(items)
+}
+
/// Get completions for `npm:` specifiers.
async fn get_npm_completions(
referrer: &ModuleSpecifier,
specifier: &str,
range: &lsp::Range,
- npm_search_api: &impl NpmSearchApi,
+ npm_search_api: &impl PackageSearchApi,
) -> Option<Vec<lsp::CompletionItem>> {
// First try to match `npm:some-package@<version-to-complete>`.
- if let Some(v_index) = parse_npm_specifier_version_index(specifier) {
- let package_name = &specifier[..v_index].strip_prefix("npm:")?;
- let v_prefix = &specifier[(v_index + 1)..];
- let versions = &npm_search_api
- .package_info(package_name)
- .await
- .ok()?
- .versions;
- let mut versions = versions.keys().collect::<Vec<_>>();
- versions.sort();
+ let bare_specifier = specifier.strip_prefix("npm:")?;
+ if let Some(v_index) = parse_bare_specifier_version_index(bare_specifier) {
+ let package_name = &bare_specifier[..v_index];
+ let v_prefix = &bare_specifier[(v_index + 1)..];
+ let versions = npm_search_api.versions(package_name).await.ok()?;
let items = versions
- .into_iter()
- .rev()
+ .iter()
.enumerate()
.filter_map(|(idx, version)| {
let version = version.to_string();
if !version.starts_with(v_prefix) {
return None;
}
- let specifier = format!("npm:{}@{}", package_name, &version);
+ let specifier = format!("npm:{}@{}", package_name, version);
let command = Some(lsp::Command {
title: "".to_string(),
command: "deno.cache".to_string(),
- arguments: Some(vec![json!([&specifier]), json!(referrer)]),
+ arguments: Some(vec![
+ json!([&specifier]),
+ json!(referrer),
+ json!({ "forceGlobalCache": true }),
+ ]),
});
let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: *range,
@@ -552,8 +708,7 @@ async fn get_npm_completions(
}
// Otherwise match `npm:<package-to-complete>`.
- let package_name_prefix = specifier.strip_prefix("npm:")?;
- let names = npm_search_api.search(package_name_prefix).await.ok()?;
+ let names = npm_search_api.search(bare_specifier).await.ok()?;
let items = names
.iter()
.enumerate()
@@ -562,7 +717,11 @@ async fn get_npm_completions(
let command = Some(lsp::Command {
title: "".to_string(),
command: "deno.cache".to_string(),
- arguments: Some(vec![json!([&specifier]), json!(referrer)]),
+ arguments: Some(vec![
+ json!([&specifier]),
+ json!(referrer),
+ json!({ "forceGlobalCache": true }),
+ ]),
});
let text_edit = Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range: *range,
@@ -640,43 +799,16 @@ mod tests {
use super::*;
use crate::cache::GlobalHttpCache;
use crate::cache::HttpCache;
+ use crate::cache::RealDenoCacheEnv;
use crate::lsp::documents::Documents;
use crate::lsp::documents::LanguageId;
- use crate::lsp::npm::NpmSearchApi;
- use crate::AnyError;
- use async_trait::async_trait;
+ use crate::lsp::search::tests::TestPackageSearchApi;
use deno_core::resolve_url;
use deno_graph::Range;
- use deno_npm::registry::NpmPackageInfo;
- use deno_npm::registry::NpmRegistryApi;
- use deno_npm::registry::TestNpmRegistryApi;
use std::collections::HashMap;
use std::path::Path;
use test_util::TempDir;
- #[derive(Default)]
- struct TestNpmSearchApi(
- HashMap<String, Arc<Vec<String>>>,
- TestNpmRegistryApi,
- );
-
- #[async_trait]
- impl NpmSearchApi for TestNpmSearchApi {
- async fn search(&self, query: &str) -> Result<Arc<Vec<String>>, AnyError> {
- match self.0.get(query) {
- Some(names) => Ok(names.clone()),
- None => Ok(Arc::new(vec![])),
- }
- }
-
- async fn package_info(
- &self,
- name: &str,
- ) -> Result<Arc<NpmPackageInfo>, AnyError> {
- self.1.package_info(name).await.map_err(|e| e.into())
- }
- }
-
fn mock_documents(
fixtures: &[(&str, &str, i32, LanguageId)],
source_fixtures: &[(&str, &str)],
@@ -846,52 +978,326 @@ mod tests {
}
#[test]
- fn test_parse_npm_specifier_version_index() {
- assert_eq!(parse_npm_specifier_version_index("npm:"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:/"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:/@"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:@"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:@/"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:@/@"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:foo"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:foo/bar"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:foo/bar@"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:@org/foo/bar"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:@org/foo/bar@"), None);
+ fn test_parse_bare_specifier_version_index() {
+ assert_eq!(parse_bare_specifier_version_index(""), None);
+ assert_eq!(parse_bare_specifier_version_index("/"), None);
+ assert_eq!(parse_bare_specifier_version_index("/@"), None);
+ assert_eq!(parse_bare_specifier_version_index("@"), None);
+ assert_eq!(parse_bare_specifier_version_index("@/"), None);
+ assert_eq!(parse_bare_specifier_version_index("@/@"), None);
+ assert_eq!(parse_bare_specifier_version_index("foo"), None);
+ assert_eq!(parse_bare_specifier_version_index("foo/bar"), None);
+ assert_eq!(parse_bare_specifier_version_index("foo/bar@"), None);
+ assert_eq!(parse_bare_specifier_version_index("@org/foo/bar"), None);
+ assert_eq!(parse_bare_specifier_version_index("@org/foo/bar@"), None);
- assert_eq!(parse_npm_specifier_version_index("npm:foo@"), Some(7));
- assert_eq!(parse_npm_specifier_version_index("npm:foo@1."), Some(7));
- assert_eq!(parse_npm_specifier_version_index("npm:@org/foo@"), Some(12));
- assert_eq!(
- parse_npm_specifier_version_index("npm:@org/foo@1."),
- Some(12)
- );
+ assert_eq!(parse_bare_specifier_version_index("foo@"), Some(3));
+ assert_eq!(parse_bare_specifier_version_index("foo@1."), Some(3));
+ assert_eq!(parse_bare_specifier_version_index("@org/foo@"), Some(8));
+ assert_eq!(parse_bare_specifier_version_index("@org/foo@1."), Some(8));
// Regression test for https://github.com/denoland/deno/issues/22325.
assert_eq!(
- parse_npm_specifier_version_index(
- "npm:@longer_than_right_one/arbitrary_string@"
+ parse_bare_specifier_version_index(
+ "@longer_than_right_one/arbitrary_string@"
),
- Some(43)
+ Some(39)
);
}
#[tokio::test]
- async fn test_get_npm_completions() {
- let npm_search_api = TestNpmSearchApi(
- vec![(
- "puppe".to_string(),
- Arc::new(vec![
- "puppeteer".to_string(),
- "puppeteer-core".to_string(),
- "puppeteer-extra-plugin-stealth".to_string(),
- "puppeteer-extra-plugin".to_string(),
- ]),
- )]
- .into_iter()
- .collect(),
- Default::default(),
+ async fn test_get_jsr_completions() {
+ let temp_dir = TempDir::default();
+ let jsr_resolver = JsrResolver::from_cache_and_lockfile(
+ Arc::new(GlobalHttpCache::new(
+ temp_dir.path().to_path_buf(),
+ RealDenoCacheEnv,
+ )),
+ None,
);
+ let jsr_search_api = TestPackageSearchApi::default()
+ .with_package_version("@std/archive", "1.0.0", &[])
+ .with_package_version("@std/assert", "1.0.0", &[])
+ .with_package_version("@std/async", "1.0.0", &[])
+ .with_package_version("@std/bytes", "1.0.0", &[]);
+ let range = lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 23,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 29,
+ },
+ };
+ let referrer = ModuleSpecifier::parse("file:///referrer.ts").unwrap();
+ let actual = get_jsr_completions(
+ &referrer,
+ "jsr:as",
+ &range,
+ &jsr_search_api,
+ &jsr_resolver,
+ )
+ .await
+ .unwrap();
+ assert_eq!(
+ actual,
+ vec![
+ lsp::CompletionItem {
+ label: "jsr:@std/assert".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000001".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/assert".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/assert"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true })
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "jsr:@std/async".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000002".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/async".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/async"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true })
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ ]
+ );
+ }
+
+ #[tokio::test]
+ async fn test_get_jsr_completions_for_versions() {
+ let temp_dir = TempDir::default();
+ let jsr_resolver = JsrResolver::from_cache_and_lockfile(
+ Arc::new(GlobalHttpCache::new(
+ temp_dir.path().to_path_buf(),
+ RealDenoCacheEnv,
+ )),
+ None,
+ );
+ let jsr_search_api = TestPackageSearchApi::default()
+ .with_package_version("@std/assert", "0.3.0", &[])
+ .with_package_version("@std/assert", "0.4.0", &[])
+ .with_package_version("@std/assert", "0.5.0", &[]);
+ let range = lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 23,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 39,
+ },
+ };
+ let referrer = ModuleSpecifier::parse("file:///referrer.ts").unwrap();
+ let actual = get_jsr_completions(
+ &referrer,
+ "jsr:@std/assert@",
+ &range,
+ &jsr_search_api,
+ &jsr_resolver,
+ )
+ .await
+ .unwrap();
+ assert_eq!(
+ actual,
+ vec![
+ lsp::CompletionItem {
+ label: "jsr:@std/assert@0.5.0".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000001".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/assert@0.5.0".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/assert@0.5.0"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "jsr:@std/assert@0.4.0".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000002".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/assert@0.4.0".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/assert@0.4.0"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "jsr:@std/assert@0.3.0".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000003".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/assert@0.3.0".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/assert@0.3.0"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ ]
+ );
+ }
+
+ #[tokio::test]
+ async fn test_get_jsr_completions_for_exports() {
+ let temp_dir = TempDir::default();
+ let jsr_resolver = JsrResolver::from_cache_and_lockfile(
+ Arc::new(GlobalHttpCache::new(
+ temp_dir.path().to_path_buf(),
+ RealDenoCacheEnv,
+ )),
+ None,
+ );
+ let jsr_search_api = TestPackageSearchApi::default().with_package_version(
+ "@std/path",
+ "0.1.0",
+ &[".", "./basename", "./common", "./constants", "./dirname"],
+ );
+ let range = lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 23,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 45,
+ },
+ };
+ let referrer = ModuleSpecifier::parse("file:///referrer.ts").unwrap();
+ let actual = get_jsr_completions(
+ &referrer,
+ "jsr:@std/path@0.1.0/co",
+ &range,
+ &jsr_search_api,
+ &jsr_resolver,
+ )
+ .await
+ .unwrap();
+ assert_eq!(
+ actual,
+ vec![
+ lsp::CompletionItem {
+ label: "jsr:@std/path@0.1.0/common".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000003".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/path@0.1.0/common".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/path@0.1.0/common"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ lsp::CompletionItem {
+ label: "jsr:@std/path@0.1.0/constants".to_string(),
+ kind: Some(lsp::CompletionItemKind::FILE),
+ detail: Some("(jsr)".to_string()),
+ sort_text: Some("0000000004".to_string()),
+ text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+ range,
+ new_text: "jsr:@std/path@0.1.0/constants".to_string(),
+ })),
+ command: Some(lsp::Command {
+ title: "".to_string(),
+ command: "deno.cache".to_string(),
+ arguments: Some(vec![
+ json!(["jsr:@std/path@0.1.0/constants"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
+ }),
+ commit_characters: Some(
+ IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
+ ),
+ ..Default::default()
+ },
+ ]
+ );
+ }
+
+ #[tokio::test]
+ async fn test_get_npm_completions() {
+ let npm_search_api = TestPackageSearchApi::default()
+ .with_package_version("puppeteer", "1.0.0", &[])
+ .with_package_version("puppeteer-core", "1.0.0", &[])
+ .with_package_version("puppeteer-extra-plugin", "1.0.0", &[])
+ .with_package_version("puppeteer-extra-plugin-stealth", "1.0.0", &[]);
let range = lsp::Range {
start: lsp::Position {
line: 0,
@@ -922,7 +1328,11 @@ mod tests {
command: Some(lsp::Command {
title: "".to_string(),
command: "deno.cache".to_string(),
- arguments: Some(vec![json!(["npm:puppeteer"]), json!(&referrer)])
+ arguments: Some(vec![
+ json!(["npm:puppeteer"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
+ ])
}),
commit_characters: Some(
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
@@ -943,7 +1353,8 @@ mod tests {
command: "deno.cache".to_string(),
arguments: Some(vec![
json!(["npm:puppeteer-core"]),
- json!(&referrer)
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -952,20 +1363,21 @@ mod tests {
..Default::default()
},
lsp::CompletionItem {
- label: "npm:puppeteer-extra-plugin-stealth".to_string(),
+ label: "npm:puppeteer-extra-plugin".to_string(),
kind: Some(lsp::CompletionItemKind::FILE),
detail: Some("(npm)".to_string()),
sort_text: Some("0000000003".to_string()),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range,
- new_text: "npm:puppeteer-extra-plugin-stealth".to_string(),
+ new_text: "npm:puppeteer-extra-plugin".to_string(),
})),
command: Some(lsp::Command {
title: "".to_string(),
command: "deno.cache".to_string(),
arguments: Some(vec![
- json!(["npm:puppeteer-extra-plugin-stealth"]),
- json!(&referrer)
+ json!(["npm:puppeteer-extra-plugin"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -974,20 +1386,21 @@ mod tests {
..Default::default()
},
lsp::CompletionItem {
- label: "npm:puppeteer-extra-plugin".to_string(),
+ label: "npm:puppeteer-extra-plugin-stealth".to_string(),
kind: Some(lsp::CompletionItemKind::FILE),
detail: Some("(npm)".to_string()),
sort_text: Some("0000000004".to_string()),
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
range,
- new_text: "npm:puppeteer-extra-plugin".to_string(),
+ new_text: "npm:puppeteer-extra-plugin-stealth".to_string(),
})),
command: Some(lsp::Command {
title: "".to_string(),
command: "deno.cache".to_string(),
arguments: Some(vec![
- json!(["npm:puppeteer-extra-plugin"]),
- json!(&referrer)
+ json!(["npm:puppeteer-extra-plugin-stealth"]),
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -1001,19 +1414,11 @@ mod tests {
#[tokio::test]
async fn test_get_npm_completions_for_versions() {
- let npm_search_api = TestNpmSearchApi::default();
- npm_search_api
- .1
- .ensure_package_version("puppeteer", "20.9.0");
- npm_search_api
- .1
- .ensure_package_version("puppeteer", "21.0.0");
- npm_search_api
- .1
- .ensure_package_version("puppeteer", "21.0.1");
- npm_search_api
- .1
- .ensure_package_version("puppeteer", "21.0.2");
+ let npm_search_api = TestPackageSearchApi::default()
+ .with_package_version("puppeteer", "20.9.0", &[])
+ .with_package_version("puppeteer", "21.0.0", &[])
+ .with_package_version("puppeteer", "21.0.1", &[])
+ .with_package_version("puppeteer", "21.0.2", &[]);
let range = lsp::Range {
start: lsp::Position {
line: 0,
@@ -1046,7 +1451,8 @@ mod tests {
command: "deno.cache".to_string(),
arguments: Some(vec![
json!(["npm:puppeteer@21.0.2"]),
- json!(&referrer)
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -1068,7 +1474,8 @@ mod tests {
command: "deno.cache".to_string(),
arguments: Some(vec![
json!(["npm:puppeteer@21.0.1"]),
- json!(&referrer)
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -1090,7 +1497,8 @@ mod tests {
command: "deno.cache".to_string(),
arguments: Some(vec![
json!(["npm:puppeteer@21.0.0"]),
- json!(&referrer)
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(
@@ -1112,7 +1520,8 @@ mod tests {
command: "deno.cache".to_string(),
arguments: Some(vec![
json!(["npm:puppeteer@20.9.0"]),
- json!(&referrer)
+ json!(&referrer),
+ json!({ "forceGlobalCache": true }),
])
}),
commit_characters: Some(