summaryrefslogtreecommitdiff
path: root/cli/lsp/sources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/sources.rs')
-rw-r--r--cli/lsp/sources.rs148
1 files changed, 147 insertions, 1 deletions
diff --git a/cli/lsp/sources.rs b/cli/lsp/sources.rs
index 1b7d6f3fa..62c76260c 100644
--- a/cli/lsp/sources.rs
+++ b/cli/lsp/sources.rs
@@ -3,6 +3,7 @@
use super::analysis;
use super::text::LineIndex;
use super::tsc;
+use super::urls::INVALID_SPECIFIER;
use crate::config_file::ConfigFile;
use crate::file_fetcher::get_source_from_bytes;
@@ -105,7 +106,7 @@ fn resolve_specifier(
}
}
-#[derive(Debug, Clone, Default)]
+#[derive(Debug, Clone)]
struct Metadata {
dependencies: Option<HashMap<String, analysis::Dependency>>,
length_utf16: usize,
@@ -115,9 +116,27 @@ struct Metadata {
maybe_warning: Option<String>,
media_type: MediaType,
source: String,
+ specifier: ModuleSpecifier,
version: String,
}
+impl Default for Metadata {
+ fn default() -> Self {
+ Self {
+ dependencies: None,
+ length_utf16: 0,
+ line_index: LineIndex::default(),
+ maybe_navigation_tree: None,
+ maybe_types: None,
+ maybe_warning: None,
+ media_type: MediaType::default(),
+ source: String::default(),
+ specifier: INVALID_SPECIFIER.clone(),
+ version: String::default(),
+ }
+ }
+}
+
impl Metadata {
fn new(
specifier: &ModuleSpecifier,
@@ -151,9 +170,28 @@ impl Metadata {
maybe_warning,
media_type: media_type.to_owned(),
source: source.to_string(),
+ specifier: specifier.clone(),
version: version.to_string(),
}
}
+
+ fn refresh(&mut self, maybe_import_map: &Option<ImportMap>) {
+ let (dependencies, maybe_types) = if let Ok(parsed_module) =
+ analysis::parse_module(&self.specifier, &self.source, &self.media_type)
+ {
+ let (deps, maybe_types) = analysis::analyze_dependencies(
+ &self.specifier,
+ &self.media_type,
+ &parsed_module,
+ maybe_import_map,
+ );
+ (Some(deps), maybe_types)
+ } else {
+ (None, None)
+ };
+ self.dependencies = dependencies;
+ self.maybe_types = maybe_types;
+ }
}
#[derive(Debug, Clone, Default)]
@@ -239,6 +277,10 @@ impl Sources {
self.0.lock().metadata.keys().cloned().collect()
}
+ pub fn set_import_map(&self, maybe_import_map: Option<ImportMap>) {
+ self.0.lock().set_import_map(maybe_import_map)
+ }
+
pub fn set_navigation_tree(
&self,
specifier: &ModuleSpecifier,
@@ -483,6 +525,13 @@ impl Inner {
}
}
+ fn set_import_map(&mut self, maybe_import_map: Option<ImportMap>) {
+ for (_, metadata) in self.metadata.iter_mut() {
+ metadata.refresh(&maybe_import_map);
+ }
+ self.maybe_import_map = maybe_import_map;
+ }
+
fn set_maybe_type(
&mut self,
specifier: &str,
@@ -517,6 +566,7 @@ mod tests {
use super::*;
use deno_core::resolve_path;
use deno_core::resolve_url;
+ use deno_core::serde_json::json;
use std::env;
use tempfile::TempDir;
@@ -655,6 +705,102 @@ mod tests {
}
#[test]
+ fn test_resolve_with_import_map() {
+ let (sources, location) = setup();
+ let import_map_json = json!({
+ "imports": {
+ "mylib": "https://deno.land/x/myLib/index.js"
+ }
+ });
+ let import_map = ImportMap::from_json(
+ "https://deno.land/x/",
+ &import_map_json.to_string(),
+ )
+ .unwrap();
+ sources.set_import_map(Some(import_map));
+ let cache = HttpCache::new(&location);
+ let mylib_specifier =
+ resolve_url("https://deno.land/x/myLib/index.js").unwrap();
+ let mut mylib_headers_map = HashMap::new();
+ mylib_headers_map.insert(
+ "content-type".to_string(),
+ "application/javascript".to_string(),
+ );
+ cache
+ .set(
+ &mylib_specifier,
+ mylib_headers_map,
+ b"export const a = \"a\";\n",
+ )
+ .unwrap();
+ let referrer = resolve_url("https://deno.land/x/mod.ts").unwrap();
+ cache
+ .set(
+ &referrer,
+ Default::default(),
+ b"export { a } from \"mylib\";",
+ )
+ .unwrap();
+ let actual = sources.resolve_import("mylib", &referrer);
+ assert_eq!(actual, Some((mylib_specifier, MediaType::JavaScript)));
+ }
+
+ #[test]
+ fn test_update_import_map() {
+ let (sources, location) = setup();
+ let import_map_json = json!({
+ "imports": {
+ "otherlib": "https://deno.land/x/otherlib/index.js"
+ }
+ });
+ let import_map = ImportMap::from_json(
+ "https://deno.land/x/",
+ &import_map_json.to_string(),
+ )
+ .unwrap();
+ sources.set_import_map(Some(import_map));
+ let cache = HttpCache::new(&location);
+ let mylib_specifier =
+ resolve_url("https://deno.land/x/myLib/index.js").unwrap();
+ let mut mylib_headers_map = HashMap::new();
+ mylib_headers_map.insert(
+ "content-type".to_string(),
+ "application/javascript".to_string(),
+ );
+ cache
+ .set(
+ &mylib_specifier,
+ mylib_headers_map,
+ b"export const a = \"a\";\n",
+ )
+ .unwrap();
+ let referrer = resolve_url("https://deno.land/x/mod.ts").unwrap();
+ cache
+ .set(
+ &referrer,
+ Default::default(),
+ b"export { a } from \"mylib\";",
+ )
+ .unwrap();
+ let actual = sources.resolve_import("mylib", &referrer);
+ assert_eq!(actual, None);
+ let import_map_json = json!({
+ "imports": {
+ "otherlib": "https://deno.land/x/otherlib/index.js",
+ "mylib": "https://deno.land/x/myLib/index.js"
+ }
+ });
+ let import_map = ImportMap::from_json(
+ "https://deno.land/x/",
+ &import_map_json.to_string(),
+ )
+ .unwrap();
+ sources.set_import_map(Some(import_map));
+ let actual = sources.resolve_import("mylib", &referrer);
+ assert_eq!(actual, Some((mylib_specifier, MediaType::JavaScript)));
+ }
+
+ #[test]
fn test_sources_resolve_specifier_non_supported_schema() {
let (sources, _) = setup();
let specifier =