summaryrefslogtreecommitdiff
path: root/cli/lsp/language_server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r--cli/lsp/language_server.rs246
1 files changed, 75 insertions, 171 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 7bed7b1bf..dc36c0540 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -4,6 +4,7 @@ use deno_ast::MediaType;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
+use deno_core::parking_lot::Mutex;
use deno_core::resolve_url;
use deno_core::serde_json;
use deno_core::serde_json::json;
@@ -12,7 +13,6 @@ use deno_core::unsync::spawn;
use deno_core::ModuleSpecifier;
use deno_graph::GraphKind;
use deno_lockfile::Lockfile;
-use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::NodeResolver;
@@ -82,7 +82,6 @@ use super::urls::LspClientUrl;
use crate::args::get_root_cert_store;
use crate::args::package_json;
use crate::args::resolve_import_map_from_specifier;
-use crate::args::snapshot_from_lockfile;
use crate::args::CaData;
use crate::args::CacheSetting;
use crate::args::CliOptions;
@@ -102,14 +101,12 @@ use crate::graph_util;
use crate::http_util::HttpClient;
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
use crate::lsp::urls::LspUrlKind;
-use crate::npm::create_npm_fs_resolver;
-use crate::npm::CliNpmRegistryApi;
+use crate::npm::create_cli_npm_resolver_for_lsp;
use crate::npm::CliNpmResolver;
-use crate::npm::ManagedCliNpmResolver;
-use crate::npm::NpmCache;
-use crate::npm::NpmCacheDir;
-use crate::npm::NpmResolution;
-use crate::npm::PackageJsonDepsInstaller;
+use crate::npm::CliNpmResolverCreateOptions;
+use crate::npm::CliNpmResolverManagedCreateOptions;
+use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
+use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::tools::fmt::format_file;
use crate::tools::fmt::format_parsed_source;
use crate::util::fs::remove_dir_all_if_exists;
@@ -130,16 +127,10 @@ impl RootCertStoreProvider for LspRootCertStoreProvider {
struct LspNpmServices {
/// When this hash changes, the services need updating
config_hash: LspNpmConfigHash,
- /// Npm's registry api.
- api: Arc<CliNpmRegistryApi>,
/// Npm's search api.
search_api: CliNpmSearchApi,
- /// Npm cache
- cache: Arc<NpmCache>,
- /// Npm resolution that is stored in memory.
- resolution: Arc<NpmResolution>,
/// Resolver for npm packages.
- resolver: Arc<dyn CliNpmResolver>,
+ resolver: Option<Arc<dyn CliNpmResolver>>,
}
#[derive(Debug, PartialEq, Eq)]
@@ -475,72 +466,6 @@ impl LanguageServer {
}
}
-fn create_npm_api_and_cache(
- dir: &DenoDir,
- http_client: Arc<HttpClient>,
- registry_url: &ModuleSpecifier,
- progress_bar: &ProgressBar,
-) -> (Arc<CliNpmRegistryApi>, Arc<NpmCache>) {
- let npm_cache = Arc::new(NpmCache::new(
- NpmCacheDir::new(dir.npm_folder_path()),
- // Use an "only" cache setting in order to make the
- // user do an explicit "cache" command and prevent
- // the cache from being filled with lots of packages while
- // the user is typing.
- CacheSetting::Only,
- Arc::new(deno_fs::RealFs),
- http_client.clone(),
- progress_bar.clone(),
- ));
- let api = Arc::new(CliNpmRegistryApi::new(
- registry_url.clone(),
- npm_cache.clone(),
- http_client,
- progress_bar.clone(),
- ));
- (api, npm_cache)
-}
-
-fn create_npm_resolver_and_resolution(
- registry_url: &ModuleSpecifier,
- progress_bar: ProgressBar,
- api: Arc<CliNpmRegistryApi>,
- npm_cache: Arc<NpmCache>,
- node_modules_dir_path: Option<PathBuf>,
- maybe_snapshot: Option<ValidSerializedNpmResolutionSnapshot>,
-) -> (Arc<dyn CliNpmResolver>, Arc<NpmResolution>) {
- let resolution = Arc::new(NpmResolution::from_serialized(
- api.clone(),
- maybe_snapshot,
- // Don't provide the lockfile. We don't want these resolvers
- // updating it. Only the cache request should update the lockfile.
- None,
- ));
- let fs = Arc::new(deno_fs::RealFs);
- let fs_resolver = create_npm_fs_resolver(
- fs.clone(),
- npm_cache,
- &progress_bar,
- registry_url.clone(),
- resolution.clone(),
- node_modules_dir_path,
- NpmSystemInfo::default(),
- );
- (
- Arc::new(ManagedCliNpmResolver::new(
- api,
- fs,
- resolution.clone(),
- fs_resolver,
- // Don't provide the lockfile. We don't want these resolvers
- // updating it. Only the cache request should update the lockfile.
- None,
- Arc::new(PackageJsonDepsInstaller::no_op()),
- )),
- resolution,
- )
-}
-
impl Inner {
fn new(client: Client) -> Self {
let dir = DenoDir::new(None).expect("could not access DENO_DIR");
@@ -571,23 +496,6 @@ impl Inner {
diagnostics_state.clone(),
);
let assets = Assets::new(ts_server.clone());
- let registry_url = CliNpmRegistryApi::default_url();
- let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
-
- let (npm_api, npm_cache) = create_npm_api_and_cache(
- &dir,
- http_client.clone(),
- registry_url,
- &progress_bar,
- );
- let (npm_resolver, npm_resolution) = create_npm_resolver_and_resolution(
- registry_url,
- progress_bar,
- npm_api.clone(),
- npm_cache.clone(),
- None,
- None,
- );
Self {
assets,
@@ -610,11 +518,8 @@ impl Inner {
module_registries_location,
npm: LspNpmServices {
config_hash: LspNpmConfigHash(0), // this will be updated in initialize
- api: npm_api,
search_api: npm_search_api,
- cache: npm_cache,
- resolution: npm_resolution,
- resolver: npm_resolver,
+ resolver: None,
},
performance,
ts_fixable_diagnostics: Default::default(),
@@ -799,41 +704,27 @@ impl Inner {
}
pub fn snapshot(&self) -> Arc<StateSnapshot> {
- // create a new snapshotted npm resolution and resolver
- let npm_resolution = Arc::new(NpmResolution::new(
- self.npm.api.clone(),
- self.npm.resolution.snapshot(),
- self.config.maybe_lockfile().cloned(),
- ));
- let node_fs = Arc::new(deno_fs::RealFs);
- let npm_resolver = Arc::new(ManagedCliNpmResolver::new(
- self.npm.api.clone(),
- node_fs.clone(),
- npm_resolution.clone(),
- create_npm_fs_resolver(
- node_fs.clone(),
- self.npm.cache.clone(),
- &ProgressBar::new(ProgressBarStyle::TextOnly),
- self.npm.api.base_url().clone(),
- npm_resolution,
- self.config.maybe_node_modules_dir_path().cloned(),
- NpmSystemInfo::default(),
- ),
- self.config.maybe_lockfile().cloned(),
- Arc::new(PackageJsonDepsInstaller::no_op()),
- ));
- let node_resolver =
- Arc::new(NodeResolver::new(node_fs, npm_resolver.clone()));
+ let maybe_state_npm_snapshot = self
+ .npm
+ .resolver
+ .as_ref()
+ .map(|resolver| resolver.clone_snapshotted())
+ .map(|resolver| {
+ let fs = Arc::new(deno_fs::RealFs);
+ let node_resolver =
+ Arc::new(NodeResolver::new(fs, resolver.clone().into_npm_resolver()));
+ StateNpmSnapshot {
+ node_resolver,
+ npm_resolver: resolver,
+ }
+ });
Arc::new(StateSnapshot {
assets: self.assets.snapshot(),
cache_metadata: self.cache_metadata.clone(),
config: self.config.snapshot(),
documents: self.documents.clone(),
maybe_import_map: self.maybe_import_map.clone(),
- npm: Some(StateNpmSnapshot {
- node_resolver,
- npm_resolver,
- }),
+ npm: maybe_state_npm_snapshot,
})
}
@@ -935,25 +826,6 @@ impl Inner {
Ok(())
}
- async fn get_npm_snapshot(
- &self,
- ) -> Option<ValidSerializedNpmResolutionSnapshot> {
- let lockfile = self.config.maybe_lockfile()?;
- let snapshot =
- match snapshot_from_lockfile(lockfile.clone(), &*self.npm.api).await {
- Ok(snapshot) => snapshot,
- Err(err) => {
- lsp_warn!("Failed getting npm snapshot from lockfile: {}", err);
- return None;
- }
- };
-
- // clear the memory cache to reduce memory usage
- self.npm.api.clear_memory_cache();
-
- Some(snapshot)
- }
-
async fn recreate_npm_services_if_necessary(&mut self) {
let deno_dir = match DenoDir::new(self.maybe_global_cache_path.clone()) {
Ok(deno_dir) => deno_dir,
@@ -967,24 +839,15 @@ impl Inner {
return; // no need to do anything
}
- let registry_url = CliNpmRegistryApi::default_url();
- let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
- (self.npm.api, self.npm.cache) = create_npm_api_and_cache(
- &deno_dir,
- self.http_client.clone(),
- registry_url,
- &progress_bar,
- );
- let maybe_snapshot = self.get_npm_snapshot().await;
- (self.npm.resolver, self.npm.resolution) =
- create_npm_resolver_and_resolution(
- registry_url,
- progress_bar,
- self.npm.api.clone(),
- self.npm.cache.clone(),
+ self.npm.resolver = Some(
+ create_npm_resolver(
+ &deno_dir,
+ &self.http_client,
+ self.config.maybe_lockfile(),
self.config.maybe_node_modules_dir_path().cloned(),
- maybe_snapshot,
- );
+ )
+ .await,
+ );
// update the hash
self.npm.config_hash = config_hash;
@@ -1217,6 +1080,45 @@ impl Inner {
}
}
+async fn create_npm_resolver(
+ deno_dir: &DenoDir,
+ http_client: &Arc<HttpClient>,
+ maybe_lockfile: Option<&Arc<Mutex<Lockfile>>>,
+ maybe_node_modules_dir_path: Option<PathBuf>,
+) -> Arc<dyn CliNpmResolver> {
+ create_cli_npm_resolver_for_lsp(CliNpmResolverCreateOptions::Managed(
+ CliNpmResolverManagedCreateOptions {
+ http_client: http_client.clone(),
+ snapshot: match maybe_lockfile {
+ Some(lockfile) => {
+ CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
+ lockfile.clone(),
+ )
+ }
+ None => CliNpmResolverManagedSnapshotOption::Specified(None),
+ },
+ // Don't provide the lockfile. We don't want these resolvers
+ // updating it. Only the cache request should update the lockfile.
+ maybe_lockfile: None,
+ fs: Arc::new(deno_fs::RealFs),
+ npm_global_cache_dir: deno_dir.npm_folder_path(),
+ // Use an "only" cache setting in order to make the
+ // user do an explicit "cache" command and prevent
+ // the cache from being filled with lots of packages while
+ // the user is typing.
+ cache_setting: CacheSetting::Only,
+ text_only_progress_bar: ProgressBar::new(ProgressBarStyle::TextOnly),
+ maybe_node_modules_path: maybe_node_modules_dir_path,
+ // do not install while resolving in the lsp—leave that to the cache command
+ package_json_installer:
+ CliNpmResolverManagedPackageJsonInstallerOption::NoInstall,
+ npm_registry_url: crate::args::npm_registry_default_url().to_owned(),
+ npm_system_info: NpmSystemInfo::default(),
+ },
+ ))
+ .await
+}
+
// lspower::LanguageServer methods. This file's LanguageServer delegates to us.
impl Inner {
async fn initialize(
@@ -1371,7 +1273,7 @@ impl Inner {
maybe_import_map: self.maybe_import_map.clone(),
maybe_config_file: self.config.maybe_config_file(),
maybe_package_json: self.maybe_package_json.as_ref(),
- npm_resolver: Some(self.npm.resolver.clone()),
+ npm_resolver: self.npm.resolver.clone(),
});
// refresh the npm specifiers because it might have discovered
@@ -1446,7 +1348,9 @@ impl Inner {
let npm_resolver = self.npm.resolver.clone();
// spawn to avoid the LSP's Send requirements
let handle = spawn(async move {
- if let Some(npm_resolver) = npm_resolver.as_managed() {
+ if let Some(npm_resolver) =
+ npm_resolver.as_ref().and_then(|r| r.as_managed())
+ {
npm_resolver.set_package_reqs(&package_reqs).await
} else {
Ok(())
@@ -2165,7 +2069,7 @@ impl Inner {
TsResponseImportMapper::new(
&self.documents,
self.maybe_import_map.as_deref(),
- self.npm.resolver.as_ref(),
+ self.npm.resolver.as_deref(),
)
}