summaryrefslogtreecommitdiff
path: root/cli/lsp/analysis.rs
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2024-02-21 02:45:00 +0000
committerGitHub <noreply@github.com>2024-02-21 02:45:00 +0000
commite32c704970d9c332367757cbd21f1905c2d11486 (patch)
tree410c36122a4b0cba64721db52734e7ba94569cff /cli/lsp/analysis.rs
parent77b90f408c4244e8ee2e4b3bd26c441d4a250671 (diff)
feat(lsp): auto-import completions for jsr specifiers (#22462)
Diffstat (limited to 'cli/lsp/analysis.rs')
-rw-r--r--cli/lsp/analysis.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs
index 96ee422c6..3dd78e428 100644
--- a/cli/lsp/analysis.rs
+++ b/cli/lsp/analysis.rs
@@ -6,6 +6,7 @@ use super::documents::Documents;
use super::language_server;
use super::tsc;
+use crate::args::jsr_url;
use crate::npm::CliNpmResolver;
use crate::tools::lint::create_linter;
use crate::util::path::specifier_to_file_path;
@@ -26,8 +27,14 @@ use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::NpmResolver;
use deno_runtime::deno_node::PathClean;
use deno_runtime::permissions::PermissionsContainer;
+use deno_semver::jsr::JsrPackageNvReference;
+use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;
+use deno_semver::package::PackageNv;
+use deno_semver::package::PackageNvReference;
use deno_semver::package::PackageReq;
+use deno_semver::package::PackageReqReference;
+use deno_semver::Version;
use import_map::ImportMap;
use once_cell::sync::Lazy;
use regex::Regex;
@@ -208,6 +215,57 @@ impl<'a> TsResponseImportMapper<'a> {
}
}
+ if let Some(jsr_path) = specifier.as_str().strip_prefix(jsr_url().as_str())
+ {
+ let mut segments = jsr_path.split('/');
+ let name = if jsr_path.starts_with('@') {
+ format!("{}/{}", segments.next()?, segments.next()?)
+ } else {
+ segments.next()?.to_string()
+ };
+ let version = Version::parse_standard(segments.next()?).ok()?;
+ let nv = PackageNv { name, version };
+ let path = segments.collect::<Vec<_>>().join("/");
+ let jsr_resolver = self.documents.get_jsr_resolver();
+ let export = jsr_resolver.lookup_export_for_path(&nv, &path)?;
+ let sub_path = (export != ".").then_some(export);
+ let mut req = None;
+ req = req.or_else(|| {
+ let import_map = self.maybe_import_map?;
+ for entry in import_map.entries_for_referrer(referrer) {
+ let Some(value) = entry.raw_value else {
+ continue;
+ };
+ let Ok(req_ref) = JsrPackageReqReference::from_str(value) else {
+ continue;
+ };
+ let req = req_ref.req();
+ if req.name == nv.name
+ && req.version_req.tag().is_none()
+ && req.version_req.matches(&nv.version)
+ {
+ return Some(req.clone());
+ }
+ }
+ None
+ });
+ req = req.or_else(|| jsr_resolver.lookup_req_for_nv(&nv));
+ let spec_str = if let Some(req) = req {
+ let req_ref = PackageReqReference { req, sub_path };
+ JsrPackageReqReference::new(req_ref).to_string()
+ } else {
+ let nv_ref = PackageNvReference { nv, sub_path };
+ JsrPackageNvReference::new(nv_ref).to_string()
+ };
+ let specifier = ModuleSpecifier::parse(&spec_str).ok()?;
+ if let Some(import_map) = self.maybe_import_map {
+ if let Some(result) = import_map.lookup(&specifier, referrer) {
+ return Some(result);
+ }
+ }
+ return Some(spec_str);
+ }
+
if let Some(npm_resolver) =
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
{