diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-04-05 18:33:01 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-05 22:33:01 +0000 |
commit | 83f92474c5e8375ebe2213b4d62d4211fd011c2f (patch) | |
tree | 2fb1d6b80c68bd1f6f1b0f07e0ed41eac3bcf356 /cli | |
parent | 61f1b8e8dc20846093a8b24a8f511a09bbf09919 (diff) |
perf(lsp): use lockfile to reduce npm pkg resolution time (#23247)
This functionality was broken. The series of events was:
1. Load the npm resolution from the lockfile.
2. Discover only a subset of the specifiers in the documents.
3. Clear the npm snapshot.
4. Redo npm resolution with the new specifiers (~500ms).
What this now does:
1. Load the npm resolution from the lockfile.
2. Discover only a subset of the specifiers in the documents and take
into account the specifiers from the lockfile.
3. Do not redo resolution (~1ms).
Diffstat (limited to 'cli')
-rw-r--r-- | cli/lsp/documents.rs | 24 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 2 | ||||
-rw-r--r-- | cli/npm/managed/resolution.rs | 8 |
3 files changed, 27 insertions, 7 deletions
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 764152938..739165652 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -855,6 +855,7 @@ pub struct Documents { /// settings. resolver: Arc<CliGraphResolver>, jsr_resolver: Arc<JsrCacheResolver>, + lockfile: Option<Arc<Mutex<Lockfile>>>, /// The npm package requirements found in npm specifiers. npm_specifier_reqs: Arc<Vec<PackageReq>>, /// Gets if any document had a node: specifier such that a @types/node package @@ -887,6 +888,7 @@ impl Documents { sloppy_imports_resolver: None, })), jsr_resolver: Arc::new(JsrCacheResolver::new(cache.clone(), None)), + lockfile: None, npm_specifier_reqs: Default::default(), has_injected_types_node_package: false, redirect_resolver: Arc::new(RedirectResolver::new(cache)), @@ -1296,12 +1298,10 @@ impl Documents { &self.jsr_resolver } - pub fn refresh_jsr_resolver( - &mut self, - lockfile: Option<Arc<Mutex<Lockfile>>>, - ) { + pub fn refresh_lockfile(&mut self, lockfile: Option<Arc<Mutex<Lockfile>>>) { self.jsr_resolver = - Arc::new(JsrCacheResolver::new(self.cache.clone(), lockfile)); + Arc::new(JsrCacheResolver::new(self.cache.clone(), lockfile.clone())); + self.lockfile = lockfile; } pub fn update_config( @@ -1339,6 +1339,7 @@ impl Documents { 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 resolver = self.resolver.as_graph_resolver(); @@ -1494,6 +1495,19 @@ impl Documents { } let mut npm_reqs = doc_analyzer.npm_reqs; + + // fill the reqs from the lockfile + if let Some(lockfile) = self.lockfile.as_ref() { + let lockfile = lockfile.lock(); + for key in lockfile.content.packages.specifiers.keys() { + if let Some(key) = key.strip_prefix("npm:") { + if let Ok(req) = PackageReq::from_str(key) { + npm_reqs.insert(req); + } + } + } + } + // Ensure a @types/node package exists when any module uses a node: specifier. // Unlike on the command line, here we just add @types/node to the npm package // requirements since this won't end up in the lockfile. diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 17145f32c..bf53623f7 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -364,7 +364,7 @@ impl LanguageServer { { let mut inner = self.0.write().await; let lockfile = inner.config.tree.root_lockfile().cloned(); - inner.documents.refresh_jsr_resolver(lockfile); + inner.documents.refresh_lockfile(lockfile); inner.refresh_npm_specifiers().await; } // now refresh the data in a read diff --git a/cli/npm/managed/resolution.rs b/cli/npm/managed/resolution.rs index 4d9c4c3e9..1903d339b 100644 --- a/cli/npm/managed/resolution.rs +++ b/cli/npm/managed/resolution.rs @@ -310,9 +310,15 @@ async fn add_package_reqs_to_snapshot( .iter() .all(|req| snapshot.package_reqs().contains_key(req)) { - log::debug!("Snapshot already up to date. Skipping pending resolution."); + log::debug!( + "Snapshot already up to date. Skipping pending npm resolution." + ); snapshot } else { + log::debug!( + /* this string is used in tests!! */ + "Running pending npm resolution." + ); let pending_resolver = get_npm_pending_resolver(api); let result = pending_resolver .resolve_pending(snapshot, package_reqs) |