mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 04:51:22 +00:00
refactor(lsp): reland move resolver fields to LspResolver (#23685)
This commit is contained in:
parent
1587387bcc
commit
cbb78e138f
@ -163,6 +163,12 @@ impl JsrCacheResolver {
|
|||||||
self.info_by_nv.insert(nv.clone(), info.clone());
|
self.info_by_nv.insert(nv.clone(), info.clone());
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn did_cache(&self) {
|
||||||
|
self.nv_by_req.retain(|_, nv| nv.is_some());
|
||||||
|
self.info_by_nv.retain(|_, info| info.is_some());
|
||||||
|
self.info_by_name.retain(|_, info| info.is_some());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_cached_url(
|
fn read_cached_url(
|
||||||
|
@ -259,8 +259,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||||||
let version = Version::parse_standard(segments.next()?).ok()?;
|
let version = Version::parse_standard(segments.next()?).ok()?;
|
||||||
let nv = PackageNv { name, version };
|
let nv = PackageNv { name, version };
|
||||||
let path = segments.collect::<Vec<_>>().join("/");
|
let path = segments.collect::<Vec<_>>().join("/");
|
||||||
let jsr_resolver = self.documents.get_jsr_resolver();
|
let export = self.resolver.jsr_lookup_export_for_path(&nv, &path)?;
|
||||||
let export = jsr_resolver.lookup_export_for_path(&nv, &path)?;
|
|
||||||
let sub_path = (export != ".").then_some(export);
|
let sub_path = (export != ".").then_some(export);
|
||||||
let mut req = None;
|
let mut req = None;
|
||||||
req = req.or_else(|| {
|
req = req.or_else(|| {
|
||||||
@ -282,7 +281,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
});
|
});
|
||||||
req = req.or_else(|| jsr_resolver.lookup_req_for_nv(&nv));
|
req = req.or_else(|| self.resolver.jsr_lookup_req_for_nv(&nv));
|
||||||
let spec_str = if let Some(req) = req {
|
let spec_str = if let Some(req) = req {
|
||||||
let req_ref = PackageReqReference { req, sub_path };
|
let req_ref = PackageReqReference { req, sub_path };
|
||||||
JsrPackageReqReference::new(req_ref).to_string()
|
JsrPackageReqReference::new(req_ref).to_string()
|
||||||
|
@ -1591,7 +1591,7 @@ mod tests {
|
|||||||
location.to_path_buf(),
|
location.to_path_buf(),
|
||||||
RealDenoCacheEnv,
|
RealDenoCacheEnv,
|
||||||
));
|
));
|
||||||
let mut documents = Documents::new(cache);
|
let mut documents = Documents::new(cache.clone());
|
||||||
for (specifier, source, version, language_id) in fixtures {
|
for (specifier, source, version, language_id) in fixtures {
|
||||||
let specifier =
|
let specifier =
|
||||||
resolve_url(specifier).expect("failed to create specifier");
|
resolve_url(specifier).expect("failed to create specifier");
|
||||||
@ -1614,7 +1614,7 @@ mod tests {
|
|||||||
config.tree.inject_config_file(config_file).await;
|
config.tree.inject_config_file(config_file).await;
|
||||||
}
|
}
|
||||||
let resolver = LspResolver::default()
|
let resolver = LspResolver::default()
|
||||||
.with_new_config(&config, None, None)
|
.with_new_config(&config, cache, None, None)
|
||||||
.await;
|
.await;
|
||||||
StateSnapshot {
|
StateSnapshot {
|
||||||
project_version: 0,
|
project_version: 0,
|
||||||
|
@ -12,7 +12,6 @@ use super::tsc::AssetDocument;
|
|||||||
|
|
||||||
use crate::cache::HttpCache;
|
use crate::cache::HttpCache;
|
||||||
use crate::graph_util::CliJsrUrlProvider;
|
use crate::graph_util::CliJsrUrlProvider;
|
||||||
use crate::jsr::JsrCacheResolver;
|
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::resolver::SloppyImportsFsEntry;
|
use crate::resolver::SloppyImportsFsEntry;
|
||||||
use crate::resolver::SloppyImportsResolution;
|
use crate::resolver::SloppyImportsResolution;
|
||||||
@ -32,9 +31,7 @@ use deno_core::futures::FutureExt;
|
|||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::source::ResolutionMode;
|
use deno_graph::source::ResolutionMode;
|
||||||
use deno_graph::GraphImport;
|
|
||||||
use deno_graph::Resolution;
|
use deno_graph::Resolution;
|
||||||
use deno_lockfile::Lockfile;
|
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
@ -705,64 +702,6 @@ pub fn to_lsp_range(range: &deno_graph::Range) -> lsp::Range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct RedirectResolver {
|
|
||||||
cache: Arc<dyn HttpCache>,
|
|
||||||
redirects: Mutex<HashMap<ModuleSpecifier, ModuleSpecifier>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RedirectResolver {
|
|
||||||
pub fn new(cache: Arc<dyn HttpCache>) -> Self {
|
|
||||||
Self {
|
|
||||||
cache,
|
|
||||||
redirects: Mutex::new(HashMap::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Option<ModuleSpecifier> {
|
|
||||||
let scheme = specifier.scheme();
|
|
||||||
if !DOCUMENT_SCHEMES.contains(&scheme) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if scheme == "http" || scheme == "https" {
|
|
||||||
let mut redirects = self.redirects.lock();
|
|
||||||
if let Some(specifier) = redirects.get(specifier) {
|
|
||||||
Some(specifier.clone())
|
|
||||||
} else {
|
|
||||||
let redirect = self.resolve_remote(specifier, 10)?;
|
|
||||||
redirects.insert(specifier.clone(), redirect.clone());
|
|
||||||
Some(redirect)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Some(specifier.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_remote(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
redirect_limit: usize,
|
|
||||||
) -> Option<ModuleSpecifier> {
|
|
||||||
if redirect_limit > 0 {
|
|
||||||
let cache_key = self.cache.cache_item_key(specifier).ok()?;
|
|
||||||
let headers = self.cache.read_headers(&cache_key).ok().flatten()?;
|
|
||||||
if let Some(location) = headers.get("location") {
|
|
||||||
let redirect =
|
|
||||||
deno_core::resolve_import(location, specifier.as_str()).ok()?;
|
|
||||||
self.resolve_remote(&redirect, redirect_limit - 1)
|
|
||||||
} else {
|
|
||||||
Some(specifier.clone())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct FileSystemDocuments {
|
struct FileSystemDocuments {
|
||||||
docs: DashMap<ModuleSpecifier, Arc<Document>>,
|
docs: DashMap<ModuleSpecifier, Arc<Document>>,
|
||||||
@ -907,21 +846,14 @@ pub struct Documents {
|
|||||||
open_docs: HashMap<ModuleSpecifier, Arc<Document>>,
|
open_docs: HashMap<ModuleSpecifier, Arc<Document>>,
|
||||||
/// Documents stored on the file system.
|
/// Documents stored on the file system.
|
||||||
file_system_docs: Arc<FileSystemDocuments>,
|
file_system_docs: Arc<FileSystemDocuments>,
|
||||||
/// Any imports to the context supplied by configuration files. This is like
|
|
||||||
/// the imports into the a module graph in CLI.
|
|
||||||
imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
|
||||||
/// A resolver that takes into account currently loaded import map and JSX
|
/// A resolver that takes into account currently loaded import map and JSX
|
||||||
/// settings.
|
/// settings.
|
||||||
resolver: Arc<LspResolver>,
|
resolver: Arc<LspResolver>,
|
||||||
jsr_resolver: Arc<JsrCacheResolver>,
|
|
||||||
lockfile: Option<Arc<Mutex<Lockfile>>>,
|
|
||||||
/// The npm package requirements found in npm specifiers.
|
/// The npm package requirements found in npm specifiers.
|
||||||
npm_specifier_reqs: Arc<Vec<PackageReq>>,
|
npm_specifier_reqs: Arc<Vec<PackageReq>>,
|
||||||
/// Gets if any document had a node: specifier such that a @types/node package
|
/// Gets if any document had a node: specifier such that a @types/node package
|
||||||
/// should be injected.
|
/// should be injected.
|
||||||
has_injected_types_node_package: bool,
|
has_injected_types_node_package: bool,
|
||||||
/// Resolves a specifier to its final redirected to specifier.
|
|
||||||
redirect_resolver: Arc<RedirectResolver>,
|
|
||||||
/// If --unstable-sloppy-imports is enabled.
|
/// If --unstable-sloppy-imports is enabled.
|
||||||
unstable_sloppy_imports: bool,
|
unstable_sloppy_imports: bool,
|
||||||
}
|
}
|
||||||
@ -934,29 +866,13 @@ impl Documents {
|
|||||||
dirty: true,
|
dirty: true,
|
||||||
open_docs: HashMap::default(),
|
open_docs: HashMap::default(),
|
||||||
file_system_docs: Default::default(),
|
file_system_docs: Default::default(),
|
||||||
imports: Default::default(),
|
|
||||||
resolver: Default::default(),
|
resolver: Default::default(),
|
||||||
jsr_resolver: Arc::new(JsrCacheResolver::new(cache.clone(), None)),
|
|
||||||
lockfile: None,
|
|
||||||
npm_specifier_reqs: Default::default(),
|
npm_specifier_reqs: Default::default(),
|
||||||
has_injected_types_node_package: false,
|
has_injected_types_node_package: false,
|
||||||
redirect_resolver: Arc::new(RedirectResolver::new(cache)),
|
|
||||||
unstable_sloppy_imports: false,
|
unstable_sloppy_imports: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(&mut self, config: &Config) {
|
|
||||||
self.config = Arc::new(config.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn module_graph_imports(&self) -> impl Iterator<Item = &ModuleSpecifier> {
|
|
||||||
self
|
|
||||||
.imports
|
|
||||||
.values()
|
|
||||||
.flat_map(|i| i.dependencies.values())
|
|
||||||
.flat_map(|value| value.get_type().or_else(|| value.get_code()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// "Open" a document from the perspective of the editor, meaning that
|
/// "Open" a document from the perspective of the editor, meaning that
|
||||||
/// requests for information from the document will come from the in-memory
|
/// requests for information from the document will come from the in-memory
|
||||||
/// representation received from the language server client, versus reading
|
/// representation received from the language server client, versus reading
|
||||||
@ -1091,11 +1007,14 @@ impl Documents {
|
|||||||
let specifier = if let Ok(jsr_req_ref) =
|
let specifier = if let Ok(jsr_req_ref) =
|
||||||
JsrPackageReqReference::from_specifier(specifier)
|
JsrPackageReqReference::from_specifier(specifier)
|
||||||
{
|
{
|
||||||
Cow::Owned(self.jsr_resolver.jsr_to_registry_url(&jsr_req_ref)?)
|
Cow::Owned(self.resolver.jsr_to_registry_url(&jsr_req_ref)?)
|
||||||
} else {
|
} else {
|
||||||
Cow::Borrowed(specifier)
|
Cow::Borrowed(specifier)
|
||||||
};
|
};
|
||||||
self.redirect_resolver.resolve(&specifier)
|
if !DOCUMENT_SCHEMES.contains(&specifier.scheme()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.resolver.resolve_redirects(&specifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1268,7 +1187,8 @@ impl Documents {
|
|||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
} else if let Some(specifier) = self
|
} else if let Some(specifier) = self
|
||||||
.resolve_imports_dependency(specifier)
|
.resolver
|
||||||
|
.resolve_graph_import(specifier)
|
||||||
.and_then(|r| r.maybe_specifier())
|
.and_then(|r| r.maybe_specifier())
|
||||||
{
|
{
|
||||||
results.push(self.resolve_dependency(specifier, referrer));
|
results.push(self.resolve_dependency(specifier, referrer));
|
||||||
@ -1297,62 +1217,18 @@ impl Documents {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the location of the on disk cache for the document store.
|
|
||||||
pub fn set_cache(&mut self, cache: Arc<dyn HttpCache>) {
|
|
||||||
// TODO update resolved dependencies?
|
|
||||||
self.cache = cache.clone();
|
|
||||||
self.redirect_resolver = Arc::new(RedirectResolver::new(cache));
|
|
||||||
self.dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_jsr_resolver(&self) -> &Arc<JsrCacheResolver> {
|
|
||||||
&self.jsr_resolver
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn refresh_lockfile(&mut self, lockfile: Option<Arc<Mutex<Lockfile>>>) {
|
|
||||||
self.jsr_resolver =
|
|
||||||
Arc::new(JsrCacheResolver::new(self.cache.clone(), lockfile.clone()));
|
|
||||||
self.lockfile = lockfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_config(
|
pub fn update_config(
|
||||||
&mut self,
|
&mut self,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
resolver: &Arc<LspResolver>,
|
resolver: &Arc<LspResolver>,
|
||||||
|
cache: Arc<dyn HttpCache>,
|
||||||
workspace_files: &BTreeSet<ModuleSpecifier>,
|
workspace_files: &BTreeSet<ModuleSpecifier>,
|
||||||
) {
|
) {
|
||||||
self.config = Arc::new(config.clone());
|
self.config = Arc::new(config.clone());
|
||||||
|
self.cache = cache;
|
||||||
let config_data = config.tree.root_data();
|
let config_data = config.tree.root_data();
|
||||||
let config_file = config_data.and_then(|d| d.config_file.as_deref());
|
let config_file = config_data.and_then(|d| d.config_file.as_deref());
|
||||||
self.resolver = resolver.clone();
|
self.resolver = resolver.clone();
|
||||||
self.jsr_resolver = Arc::new(JsrCacheResolver::new(
|
|
||||||
self.cache.clone(),
|
|
||||||
config.tree.root_lockfile().cloned(),
|
|
||||||
));
|
|
||||||
self.lockfile = config.tree.root_lockfile().cloned();
|
|
||||||
self.redirect_resolver =
|
|
||||||
Arc::new(RedirectResolver::new(self.cache.clone()));
|
|
||||||
let graph_resolver = self.resolver.as_graph_resolver();
|
|
||||||
let npm_resolver = self.resolver.as_graph_npm_resolver();
|
|
||||||
self.imports = Arc::new(
|
|
||||||
if let Some(Ok(imports)) = config_file.map(|cf| cf.to_maybe_imports()) {
|
|
||||||
imports
|
|
||||||
.into_iter()
|
|
||||||
.map(|(referrer, imports)| {
|
|
||||||
let graph_import = GraphImport::new(
|
|
||||||
&referrer,
|
|
||||||
imports,
|
|
||||||
&CliJsrUrlProvider,
|
|
||||||
Some(graph_resolver),
|
|
||||||
Some(npm_resolver),
|
|
||||||
);
|
|
||||||
(referrer, graph_import)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
IndexMap::new()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
self.unstable_sloppy_imports = config_file
|
self.unstable_sloppy_imports = config_file
|
||||||
.map(|c| c.has_unstable("sloppy-imports"))
|
.map(|c| c.has_unstable("sloppy-imports"))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
@ -1450,7 +1326,7 @@ impl Documents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fill the reqs from the lockfile
|
// fill the reqs from the lockfile
|
||||||
if let Some(lockfile) = self.lockfile.as_ref() {
|
if let Some(lockfile) = self.config.tree.root_lockfile() {
|
||||||
let lockfile = lockfile.lock();
|
let lockfile = lockfile.lock();
|
||||||
for key in lockfile.content.packages.specifiers.keys() {
|
for key in lockfile.content.packages.specifiers.keys() {
|
||||||
if let Some(key) = key.strip_prefix("npm:") {
|
if let Some(key) = key.strip_prefix("npm:") {
|
||||||
@ -1505,19 +1381,6 @@ impl Documents {
|
|||||||
Some((doc.specifier().clone(), media_type))
|
Some((doc.specifier().clone(), media_type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate through any "imported" modules, checking to see if a dependency
|
|
||||||
/// is available. This is used to provide "global" imports like the JSX import
|
|
||||||
/// source.
|
|
||||||
fn resolve_imports_dependency(&self, specifier: &str) -> Option<&Resolution> {
|
|
||||||
for graph_imports in self.imports.values() {
|
|
||||||
let maybe_dep = graph_imports.dependencies.get(specifier);
|
|
||||||
if maybe_dep.is_some() {
|
|
||||||
return maybe_dep.map(|d| &d.maybe_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_resolve_npm_req_ref(
|
fn node_resolve_npm_req_ref(
|
||||||
@ -1691,20 +1554,20 @@ mod tests {
|
|||||||
use test_util::PathRef;
|
use test_util::PathRef;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
fn setup(temp_dir: &TempDir) -> (Documents, PathRef) {
|
fn setup(temp_dir: &TempDir) -> (Documents, PathRef, Arc<dyn HttpCache>) {
|
||||||
let location = temp_dir.path().join("deps");
|
let location = temp_dir.path().join("deps");
|
||||||
let cache = Arc::new(GlobalHttpCache::new(
|
let cache = Arc::new(GlobalHttpCache::new(
|
||||||
location.to_path_buf(),
|
location.to_path_buf(),
|
||||||
RealDenoCacheEnv,
|
RealDenoCacheEnv,
|
||||||
));
|
));
|
||||||
let documents = Documents::new(cache);
|
let documents = Documents::new(cache.clone());
|
||||||
(documents, location)
|
(documents, location, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_documents_open_close() {
|
fn test_documents_open_close() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let (mut documents, _) = setup(&temp_dir);
|
let (mut documents, _, _) = setup(&temp_dir);
|
||||||
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
|
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
|
||||||
let content = r#"import * as b from "./b.ts";
|
let content = r#"import * as b from "./b.ts";
|
||||||
console.log(b);
|
console.log(b);
|
||||||
@ -1730,7 +1593,7 @@ console.log(b);
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_documents_change() {
|
fn test_documents_change() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let (mut documents, _) = setup(&temp_dir);
|
let (mut documents, _, _) = setup(&temp_dir);
|
||||||
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
|
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
|
||||||
let content = r#"import * as b from "./b.ts";
|
let content = r#"import * as b from "./b.ts";
|
||||||
console.log(b);
|
console.log(b);
|
||||||
@ -1774,7 +1637,7 @@ console.log(b, "hello deno");
|
|||||||
// it should never happen that a user of this API causes this to happen,
|
// it should never happen that a user of this API causes this to happen,
|
||||||
// but we'll guard against it anyway
|
// but we'll guard against it anyway
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let (mut documents, documents_path) = setup(&temp_dir);
|
let (mut documents, documents_path, _) = setup(&temp_dir);
|
||||||
let file_path = documents_path.join("file.ts");
|
let file_path = documents_path.join("file.ts");
|
||||||
let file_specifier = ModuleSpecifier::from_file_path(&file_path).unwrap();
|
let file_specifier = ModuleSpecifier::from_file_path(&file_path).unwrap();
|
||||||
documents_path.create_dir_all();
|
documents_path.create_dir_all();
|
||||||
@ -1802,7 +1665,7 @@ console.log(b, "hello deno");
|
|||||||
// it should never happen that a user of this API causes this to happen,
|
// it should never happen that a user of this API causes this to happen,
|
||||||
// but we'll guard against it anyway
|
// but we'll guard against it anyway
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let (mut documents, documents_path) = setup(&temp_dir);
|
let (mut documents, documents_path, cache) = setup(&temp_dir);
|
||||||
fs::create_dir_all(&documents_path).unwrap();
|
fs::create_dir_all(&documents_path).unwrap();
|
||||||
|
|
||||||
let file1_path = documents_path.join("file1.ts");
|
let file1_path = documents_path.join("file1.ts");
|
||||||
@ -1851,9 +1714,14 @@ console.log(b, "hello deno");
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let resolver = LspResolver::default()
|
let resolver = LspResolver::default()
|
||||||
.with_new_config(&config, None, None)
|
.with_new_config(&config, cache.clone(), None, None)
|
||||||
.await;
|
.await;
|
||||||
documents.update_config(&config, &resolver, &workspace_files);
|
documents.update_config(
|
||||||
|
&config,
|
||||||
|
&resolver,
|
||||||
|
cache.clone(),
|
||||||
|
&workspace_files,
|
||||||
|
);
|
||||||
|
|
||||||
// open the document
|
// open the document
|
||||||
let document = documents.open(
|
let document = documents.open(
|
||||||
@ -1895,9 +1763,9 @@ console.log(b, "hello deno");
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let resolver = LspResolver::default()
|
let resolver = LspResolver::default()
|
||||||
.with_new_config(&config, None, None)
|
.with_new_config(&config, cache.clone(), None, None)
|
||||||
.await;
|
.await;
|
||||||
documents.update_config(&config, &resolver, &workspace_files);
|
documents.update_config(&config, &resolver, cache, &workspace_files);
|
||||||
|
|
||||||
// check the document's dependencies
|
// check the document's dependencies
|
||||||
let document = documents.get(&file1_specifier).unwrap();
|
let document = documents.get(&file1_specifier).unwrap();
|
||||||
|
@ -316,10 +316,17 @@ impl LanguageServer {
|
|||||||
|
|
||||||
// now get the lock back to update with the new information
|
// now get the lock back to update with the new information
|
||||||
let mut inner = self.0.write().await;
|
let mut inner = self.0.write().await;
|
||||||
let lockfile = inner.config.tree.root_lockfile().cloned();
|
inner.resolver.did_cache();
|
||||||
inner.documents.refresh_lockfile(lockfile);
|
|
||||||
inner.refresh_npm_specifiers().await;
|
inner.refresh_npm_specifiers().await;
|
||||||
inner.post_cache(result.mark).await;
|
inner.diagnostics_server.invalidate_all();
|
||||||
|
inner.project_changed([], false);
|
||||||
|
inner
|
||||||
|
.ts_server
|
||||||
|
.cleanup_semantic_cache(inner.snapshot())
|
||||||
|
.await;
|
||||||
|
inner.send_diagnostics_update();
|
||||||
|
inner.send_testing_update();
|
||||||
|
inner.performance.measure(result.mark);
|
||||||
}
|
}
|
||||||
Ok(Some(json!(true)))
|
Ok(Some(json!(true)))
|
||||||
}
|
}
|
||||||
@ -689,7 +696,6 @@ impl Inner {
|
|||||||
.clone()
|
.clone()
|
||||||
.map(|c| c as Arc<dyn HttpCache>)
|
.map(|c| c as Arc<dyn HttpCache>)
|
||||||
.unwrap_or(self.global_cache.clone());
|
.unwrap_or(self.global_cache.clone());
|
||||||
self.documents.set_cache(self.cache.clone());
|
|
||||||
self.cache_metadata.set_cache(self.cache.clone());
|
self.cache_metadata.set_cache(self.cache.clone());
|
||||||
self.performance.measure(mark);
|
self.performance.measure(mark);
|
||||||
}
|
}
|
||||||
@ -781,8 +787,6 @@ impl Inner {
|
|||||||
self.config.update_capabilities(¶ms.capabilities);
|
self.config.update_capabilities(¶ms.capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.documents.initialize(&self.config);
|
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
.ts_server
|
.ts_server
|
||||||
.start(self.config.internal_inspect().to_address())
|
.start(self.config.internal_inspect().to_address())
|
||||||
@ -986,10 +990,14 @@ impl Inner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn refresh_resolver(&mut self) {
|
||||||
self.resolver = self
|
self.resolver = self
|
||||||
.resolver
|
.resolver
|
||||||
.with_new_config(
|
.with_new_config(
|
||||||
&self.config,
|
&self.config,
|
||||||
|
self.cache.clone(),
|
||||||
self.maybe_global_cache_path.as_deref(),
|
self.maybe_global_cache_path.as_deref(),
|
||||||
Some(&self.http_client),
|
Some(&self.http_client),
|
||||||
)
|
)
|
||||||
@ -1000,6 +1008,7 @@ impl Inner {
|
|||||||
self.documents.update_config(
|
self.documents.update_config(
|
||||||
&self.config,
|
&self.config,
|
||||||
&self.resolver,
|
&self.resolver,
|
||||||
|
self.cache.clone(),
|
||||||
&self.workspace_files,
|
&self.workspace_files,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1133,6 +1142,7 @@ impl Inner {
|
|||||||
self.refresh_workspace_files();
|
self.refresh_workspace_files();
|
||||||
self.refresh_config_tree().await;
|
self.refresh_config_tree().await;
|
||||||
self.update_cache();
|
self.update_cache();
|
||||||
|
self.refresh_resolver().await;
|
||||||
self.refresh_documents_config().await;
|
self.refresh_documents_config().await;
|
||||||
self.diagnostics_server.invalidate_all();
|
self.diagnostics_server.invalidate_all();
|
||||||
self.send_diagnostics_update();
|
self.send_diagnostics_update();
|
||||||
@ -1181,6 +1191,7 @@ impl Inner {
|
|||||||
self.workspace_files_hash = 0;
|
self.workspace_files_hash = 0;
|
||||||
self.refresh_workspace_files();
|
self.refresh_workspace_files();
|
||||||
self.refresh_config_tree().await;
|
self.refresh_config_tree().await;
|
||||||
|
self.refresh_resolver().await;
|
||||||
deno_config_changes.extend(changes.iter().filter_map(|(s, e)| {
|
deno_config_changes.extend(changes.iter().filter_map(|(s, e)| {
|
||||||
self.config.tree.watched_file_type(s).and_then(|t| {
|
self.config.tree.watched_file_type(s).and_then(|t| {
|
||||||
let configuration_type = match t.1 {
|
let configuration_type = match t.1 {
|
||||||
@ -1482,10 +1493,7 @@ impl Inner {
|
|||||||
if let Ok(jsr_req_ref) =
|
if let Ok(jsr_req_ref) =
|
||||||
JsrPackageReqReference::from_specifier(specifier)
|
JsrPackageReqReference::from_specifier(specifier)
|
||||||
{
|
{
|
||||||
if let Some(url) = self
|
if let Some(url) = self.resolver.jsr_to_registry_url(&jsr_req_ref)
|
||||||
.documents
|
|
||||||
.get_jsr_resolver()
|
|
||||||
.jsr_to_registry_url(&jsr_req_ref)
|
|
||||||
{
|
{
|
||||||
result = format!("{result} (<{url}>)");
|
result = format!("{result} (<{url}>)");
|
||||||
}
|
}
|
||||||
@ -2961,6 +2969,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
|||||||
{
|
{
|
||||||
let mut ls = self.0.write().await;
|
let mut ls = self.0.write().await;
|
||||||
init_log_file(ls.config.log_file());
|
init_log_file(ls.config.log_file());
|
||||||
|
ls.refresh_resolver().await;
|
||||||
ls.refresh_documents_config().await;
|
ls.refresh_documents_config().await;
|
||||||
ls.diagnostics_server.invalidate_all();
|
ls.diagnostics_server.invalidate_all();
|
||||||
ls.send_diagnostics_update();
|
ls.send_diagnostics_update();
|
||||||
@ -3095,6 +3104,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
|||||||
let mut ls = self.0.write().await;
|
let mut ls = self.0.write().await;
|
||||||
ls.refresh_workspace_files();
|
ls.refresh_workspace_files();
|
||||||
ls.refresh_config_tree().await;
|
ls.refresh_config_tree().await;
|
||||||
|
ls.refresh_resolver().await;
|
||||||
ls.refresh_documents_config().await;
|
ls.refresh_documents_config().await;
|
||||||
ls.diagnostics_server.invalidate_all();
|
ls.diagnostics_server.invalidate_all();
|
||||||
ls.send_diagnostics_update();
|
ls.send_diagnostics_update();
|
||||||
@ -3354,20 +3364,6 @@ impl Inner {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn post_cache(&mut self, mark: PerformanceMark) {
|
|
||||||
// Now that we have dependencies loaded, we need to re-analyze all the files.
|
|
||||||
// For that we're invalidating all the existing diagnostics and restarting
|
|
||||||
// the language server for TypeScript (as it might hold to some stale
|
|
||||||
// documents).
|
|
||||||
self.diagnostics_server.invalidate_all();
|
|
||||||
self.project_changed([], false);
|
|
||||||
self.ts_server.cleanup_semantic_cache(self.snapshot()).await;
|
|
||||||
self.send_diagnostics_update();
|
|
||||||
self.send_testing_update();
|
|
||||||
|
|
||||||
self.performance.measure(mark);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_performance(&self) -> Value {
|
fn get_performance(&self) -> Value {
|
||||||
let averages = self.performance.averages();
|
let averages = self.performance.averages();
|
||||||
json!({ "averages": averages })
|
json!({ "averages": averages })
|
||||||
|
@ -4,7 +4,9 @@ use crate::args::package_json;
|
|||||||
use crate::args::CacheSetting;
|
use crate::args::CacheSetting;
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
|
use crate::graph_util::CliJsrUrlProvider;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
|
use crate::jsr::JsrCacheResolver;
|
||||||
use crate::lsp::config::Config;
|
use crate::lsp::config::Config;
|
||||||
use crate::lsp::config::ConfigData;
|
use crate::lsp::config::ConfigData;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
@ -21,10 +23,14 @@ use crate::resolver::CliGraphResolverOptions;
|
|||||||
use crate::resolver::CliNodeResolver;
|
use crate::resolver::CliNodeResolver;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::progress_bar::ProgressBarStyle;
|
use crate::util::progress_bar::ProgressBarStyle;
|
||||||
|
use deno_cache_dir::HttpCache;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_graph::source::NpmResolver;
|
use deno_graph::source::NpmResolver;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
|
use deno_graph::GraphImport;
|
||||||
use deno_graph::ModuleSpecifier;
|
use deno_graph::ModuleSpecifier;
|
||||||
|
use deno_graph::Resolution;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
@ -33,9 +39,13 @@ use deno_runtime::deno_node::NodeResolver;
|
|||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::fs_util::specifier_to_file_path;
|
use deno_runtime::fs_util::specifier_to_file_path;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use indexmap::IndexMap;
|
||||||
use package_json::PackageJsonDepsProvider;
|
use package_json::PackageJsonDepsProvider;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -43,19 +53,25 @@ use std::sync::Arc;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LspResolver {
|
pub struct LspResolver {
|
||||||
graph_resolver: Arc<CliGraphResolver>,
|
graph_resolver: Arc<CliGraphResolver>,
|
||||||
|
jsr_resolver: Option<Arc<JsrCacheResolver>>,
|
||||||
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
||||||
node_resolver: Option<Arc<CliNodeResolver>>,
|
node_resolver: Option<Arc<CliNodeResolver>>,
|
||||||
npm_config_hash: LspNpmConfigHash,
|
npm_config_hash: LspNpmConfigHash,
|
||||||
|
redirect_resolver: Option<Arc<RedirectResolver>>,
|
||||||
|
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
||||||
config: Arc<Config>,
|
config: Arc<Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LspResolver {
|
impl Default for LspResolver {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
graph_resolver: create_graph_resolver(&Default::default(), None, None),
|
graph_resolver: create_graph_resolver(None, None, None),
|
||||||
|
jsr_resolver: None,
|
||||||
npm_resolver: None,
|
npm_resolver: None,
|
||||||
node_resolver: None,
|
node_resolver: None,
|
||||||
npm_config_hash: LspNpmConfigHash(0),
|
npm_config_hash: LspNpmConfigHash(0),
|
||||||
|
redirect_resolver: None,
|
||||||
|
graph_imports: Default::default(),
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,15 +81,16 @@ impl LspResolver {
|
|||||||
pub async fn with_new_config(
|
pub async fn with_new_config(
|
||||||
&self,
|
&self,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
|
cache: Arc<dyn HttpCache>,
|
||||||
global_cache_path: Option<&Path>,
|
global_cache_path: Option<&Path>,
|
||||||
http_client: Option<&Arc<HttpClient>>,
|
http_client: Option<&Arc<HttpClient>>,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let npm_config_hash = LspNpmConfigHash::new(config, global_cache_path);
|
let npm_config_hash = LspNpmConfigHash::new(config, global_cache_path);
|
||||||
|
let config_data = config.tree.root_data();
|
||||||
let mut npm_resolver = None;
|
let mut npm_resolver = None;
|
||||||
let mut node_resolver = None;
|
let mut node_resolver = None;
|
||||||
if npm_config_hash != self.npm_config_hash {
|
if npm_config_hash != self.npm_config_hash {
|
||||||
if let (Some(http_client), Some(config_data)) =
|
if let (Some(http_client), Some(config_data)) = (http_client, config_data)
|
||||||
(http_client, config.tree.root_data())
|
|
||||||
{
|
{
|
||||||
npm_resolver =
|
npm_resolver =
|
||||||
create_npm_resolver(config_data, global_cache_path, http_client)
|
create_npm_resolver(config_data, global_cache_path, http_client)
|
||||||
@ -85,15 +102,44 @@ impl LspResolver {
|
|||||||
node_resolver = self.node_resolver.clone();
|
node_resolver = self.node_resolver.clone();
|
||||||
}
|
}
|
||||||
let graph_resolver = create_graph_resolver(
|
let graph_resolver = create_graph_resolver(
|
||||||
config,
|
config_data,
|
||||||
npm_resolver.as_ref(),
|
npm_resolver.as_ref(),
|
||||||
node_resolver.as_ref(),
|
node_resolver.as_ref(),
|
||||||
);
|
);
|
||||||
|
let jsr_resolver = Some(Arc::new(JsrCacheResolver::new(
|
||||||
|
cache.clone(),
|
||||||
|
config_data.and_then(|d| d.lockfile.clone()),
|
||||||
|
)));
|
||||||
|
let redirect_resolver = Some(Arc::new(RedirectResolver::new(cache)));
|
||||||
|
let graph_imports = config_data
|
||||||
|
.and_then(|d| d.config_file.as_ref())
|
||||||
|
.and_then(|cf| cf.to_maybe_imports().ok())
|
||||||
|
.map(|imports| {
|
||||||
|
Arc::new(
|
||||||
|
imports
|
||||||
|
.into_iter()
|
||||||
|
.map(|(referrer, imports)| {
|
||||||
|
let graph_import = GraphImport::new(
|
||||||
|
&referrer,
|
||||||
|
imports,
|
||||||
|
&CliJsrUrlProvider,
|
||||||
|
Some(graph_resolver.as_ref()),
|
||||||
|
Some(graph_resolver.as_ref()),
|
||||||
|
);
|
||||||
|
(referrer, graph_import)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
graph_resolver,
|
graph_resolver,
|
||||||
|
jsr_resolver,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
npm_config_hash,
|
npm_config_hash,
|
||||||
|
redirect_resolver,
|
||||||
|
graph_imports,
|
||||||
config: Arc::new(config.clone()),
|
config: Arc::new(config.clone()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -103,19 +149,26 @@ impl LspResolver {
|
|||||||
self.npm_resolver.as_ref().map(|r| r.clone_snapshotted());
|
self.npm_resolver.as_ref().map(|r| r.clone_snapshotted());
|
||||||
let node_resolver = create_node_resolver(npm_resolver.as_ref());
|
let node_resolver = create_node_resolver(npm_resolver.as_ref());
|
||||||
let graph_resolver = create_graph_resolver(
|
let graph_resolver = create_graph_resolver(
|
||||||
&self.config,
|
self.config.tree.root_data(),
|
||||||
npm_resolver.as_ref(),
|
npm_resolver.as_ref(),
|
||||||
node_resolver.as_ref(),
|
node_resolver.as_ref(),
|
||||||
);
|
);
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
graph_resolver,
|
graph_resolver,
|
||||||
|
jsr_resolver: self.jsr_resolver.clone(),
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
npm_config_hash: self.npm_config_hash.clone(),
|
npm_config_hash: self.npm_config_hash.clone(),
|
||||||
|
redirect_resolver: self.redirect_resolver.clone(),
|
||||||
|
graph_imports: self.graph_imports.clone(),
|
||||||
config: self.config.clone(),
|
config: self.config.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn did_cache(&self) {
|
||||||
|
self.jsr_resolver.as_ref().inspect(|r| r.did_cache());
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn set_npm_package_reqs(
|
pub async fn set_npm_package_reqs(
|
||||||
&self,
|
&self,
|
||||||
reqs: &[PackageReq],
|
reqs: &[PackageReq],
|
||||||
@ -136,10 +189,49 @@ impl LspResolver {
|
|||||||
self.graph_resolver.as_ref()
|
self.graph_resolver.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn jsr_to_registry_url(
|
||||||
|
&self,
|
||||||
|
req_ref: &JsrPackageReqReference,
|
||||||
|
) -> Option<ModuleSpecifier> {
|
||||||
|
self.jsr_resolver.as_ref()?.jsr_to_registry_url(req_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jsr_lookup_export_for_path(
|
||||||
|
&self,
|
||||||
|
nv: &PackageNv,
|
||||||
|
path: &str,
|
||||||
|
) -> Option<String> {
|
||||||
|
self.jsr_resolver.as_ref()?.lookup_export_for_path(nv, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jsr_lookup_req_for_nv(&self, nv: &PackageNv) -> Option<PackageReq> {
|
||||||
|
self.jsr_resolver.as_ref()?.lookup_req_for_nv(nv)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn maybe_managed_npm_resolver(&self) -> Option<&ManagedCliNpmResolver> {
|
pub fn maybe_managed_npm_resolver(&self) -> Option<&ManagedCliNpmResolver> {
|
||||||
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
|
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn graph_import_specifiers(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = &ModuleSpecifier> {
|
||||||
|
self
|
||||||
|
.graph_imports
|
||||||
|
.values()
|
||||||
|
.flat_map(|i| i.dependencies.values())
|
||||||
|
.flat_map(|value| value.get_type().or_else(|| value.get_code()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_graph_import(&self, specifier: &str) -> Option<&Resolution> {
|
||||||
|
for graph_imports in self.graph_imports.values() {
|
||||||
|
let maybe_dep = graph_imports.dependencies.get(specifier);
|
||||||
|
if maybe_dep.is_some() {
|
||||||
|
return maybe_dep.map(|d| &d.maybe_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
if let Some(npm_resolver) = &self.npm_resolver {
|
if let Some(npm_resolver) = &self.npm_resolver {
|
||||||
return npm_resolver.in_npm_package(specifier);
|
return npm_resolver.in_npm_package(specifier);
|
||||||
@ -203,6 +295,16 @@ impl LspResolver {
|
|||||||
node_resolver
|
node_resolver
|
||||||
.get_closest_package_json(referrer, &PermissionsContainer::allow_all())
|
.get_closest_package_json(referrer, &PermissionsContainer::allow_all())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_redirects(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<ModuleSpecifier> {
|
||||||
|
let Some(redirect_resolver) = self.redirect_resolver.as_ref() else {
|
||||||
|
return Some(specifier.clone());
|
||||||
|
};
|
||||||
|
redirect_resolver.resolve(specifier)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_npm_resolver(
|
async fn create_npm_resolver(
|
||||||
@ -275,11 +377,10 @@ fn create_node_resolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_graph_resolver(
|
fn create_graph_resolver(
|
||||||
config: &Config,
|
config_data: Option<&ConfigData>,
|
||||||
npm_resolver: Option<&Arc<dyn CliNpmResolver>>,
|
npm_resolver: Option<&Arc<dyn CliNpmResolver>>,
|
||||||
node_resolver: Option<&Arc<CliNodeResolver>>,
|
node_resolver: Option<&Arc<CliNodeResolver>>,
|
||||||
) -> Arc<CliGraphResolver> {
|
) -> Arc<CliGraphResolver> {
|
||||||
let config_data = config.tree.root_data();
|
|
||||||
let config_file = config_data.and_then(|d| d.config_file.as_deref());
|
let config_file = config_data.and_then(|d| d.config_file.as_deref());
|
||||||
Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
|
Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
|
||||||
node_resolver: node_resolver.cloned(),
|
node_resolver: node_resolver.cloned(),
|
||||||
@ -296,7 +397,7 @@ fn create_graph_resolver(
|
|||||||
maybe_import_map: config_data.and_then(|d| d.import_map.clone()),
|
maybe_import_map: config_data.and_then(|d| d.import_map.clone()),
|
||||||
maybe_vendor_dir: config_data.and_then(|d| d.vendor_dir.as_ref()),
|
maybe_vendor_dir: config_data.and_then(|d| d.vendor_dir.as_ref()),
|
||||||
bare_node_builtins_enabled: config_file
|
bare_node_builtins_enabled: config_file
|
||||||
.map(|config| config.has_unstable("bare-node-builtins"))
|
.map(|cf| cf.has_unstable("bare-node-builtins"))
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
// Don't set this for the LSP because instead we'll use the OpenDocumentsLoader
|
// Don't set this for the LSP because instead we'll use the OpenDocumentsLoader
|
||||||
// because it's much easier and we get diagnostics/quick fixes about a redirected
|
// because it's much easier and we get diagnostics/quick fixes about a redirected
|
||||||
@ -326,3 +427,56 @@ impl LspNpmConfigHash {
|
|||||||
Self(hasher.finish())
|
Self(hasher.finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RedirectResolver {
|
||||||
|
cache: Arc<dyn HttpCache>,
|
||||||
|
redirects: Mutex<HashMap<ModuleSpecifier, ModuleSpecifier>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RedirectResolver {
|
||||||
|
pub fn new(cache: Arc<dyn HttpCache>) -> Self {
|
||||||
|
Self {
|
||||||
|
cache,
|
||||||
|
redirects: Mutex::new(HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<ModuleSpecifier> {
|
||||||
|
if matches!(specifier.scheme(), "http" | "https") {
|
||||||
|
let mut redirects = self.redirects.lock();
|
||||||
|
if let Some(specifier) = redirects.get(specifier) {
|
||||||
|
Some(specifier.clone())
|
||||||
|
} else {
|
||||||
|
let redirect = self.resolve_remote(specifier, 10)?;
|
||||||
|
redirects.insert(specifier.clone(), redirect.clone());
|
||||||
|
Some(redirect)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(specifier.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_remote(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
redirect_limit: usize,
|
||||||
|
) -> Option<ModuleSpecifier> {
|
||||||
|
if redirect_limit > 0 {
|
||||||
|
let cache_key = self.cache.cache_item_key(specifier).ok()?;
|
||||||
|
let headers = self.cache.read_headers(&cache_key).ok().flatten()?;
|
||||||
|
if let Some(location) = headers.get("location") {
|
||||||
|
let redirect =
|
||||||
|
deno_core::resolve_import(location, specifier.as_str()).ok()?;
|
||||||
|
self.resolve_remote(&redirect, redirect_limit - 1)
|
||||||
|
} else {
|
||||||
|
Some(specifier.clone())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4130,9 +4130,9 @@ fn op_script_names(state: &mut OpState) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inject these next because they're global
|
// inject these next because they're global
|
||||||
for import in documents.module_graph_imports() {
|
for specifier in state.state_snapshot.resolver.graph_import_specifiers() {
|
||||||
if seen.insert(import.as_str()) {
|
if seen.insert(specifier.as_str()) {
|
||||||
result.push(import.to_string());
|
result.push(specifier.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5110,7 +5110,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let resolver = LspResolver::default()
|
let resolver = LspResolver::default()
|
||||||
.with_new_config(&config, None, None)
|
.with_new_config(&config, cache.clone(), None, None)
|
||||||
.await;
|
.await;
|
||||||
StateSnapshot {
|
StateSnapshot {
|
||||||
project_version: 0,
|
project_version: 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user