summaryrefslogtreecommitdiff
path: root/cli/lsp/config.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-07-10 17:45:09 -0400
committerGitHub <noreply@github.com>2023-07-10 21:45:09 +0000
commit8dd9d5f5239f9f842f7096a540f866bd4f10b72c (patch)
tree159ea977036a2ed76ce61d3ba2da9239a6f287a3 /cli/lsp/config.rs
parent629d09b149ab42cc4c3cebc41e0f23112ace891c (diff)
refactor(lsp): move config file related code to config.rs (#19790)
Will make #19788 easier.
Diffstat (limited to 'cli/lsp/config.rs')
-rw-r--r--cli/lsp/config.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 0a25e2b99..4d008a290 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -1,16 +1,22 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use super::logging::lsp_log;
+use crate::args::ConfigFile;
+use crate::lsp::logging::lsp_warn;
+use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::util::path::specifier_to_file_path;
use deno_core::error::AnyError;
+use deno_core::parking_lot::Mutex;
use deno_core::serde::Deserialize;
use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::serde_json::Value;
use deno_core::ModuleSpecifier;
+use deno_lockfile::Lockfile;
use lsp::Url;
use std::collections::BTreeMap;
use std::collections::HashMap;
+use std::path::PathBuf;
use std::sync::Arc;
use tower_lsp::lsp_types as lsp;
@@ -427,6 +433,16 @@ pub struct Settings {
pub workspace: WorkspaceSettings,
}
+/// Contains the config file and dependent information.
+#[derive(Debug)]
+struct LspConfigFileInfo {
+ pub config_file: ConfigFile,
+ /// An optional deno.lock file, which is resolved relative to the config file.
+ pub maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
+ /// The canonicalized node_modules directory, which is found relative to the config file.
+ pub maybe_node_modules_dir: Option<PathBuf>,
+}
+
#[derive(Debug)]
pub struct Config {
pub client_capabilities: ClientCapabilities,
@@ -434,6 +450,9 @@ pub struct Config {
pub root_uri: Option<ModuleSpecifier>,
settings: Settings,
pub workspace_folders: Option<Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>>,
+ /// An optional configuration file which has been specified in the client
+ /// options along with some data that is computed after the config file is set.
+ maybe_config_file_info: Option<LspConfigFileInfo>,
}
impl Config {
@@ -445,9 +464,40 @@ impl Config {
root_uri: None,
settings: Default::default(),
workspace_folders: None,
+ maybe_config_file_info: None,
}
}
+ pub fn maybe_node_modules_dir_path(&self) -> Option<&PathBuf> {
+ self
+ .maybe_config_file_info
+ .as_ref()
+ .and_then(|p| p.maybe_node_modules_dir.as_ref())
+ }
+
+ pub fn maybe_config_file(&self) -> Option<&ConfigFile> {
+ self.maybe_config_file_info.as_ref().map(|c| &c.config_file)
+ }
+
+ pub fn maybe_lockfile(&self) -> Option<&Arc<Mutex<Lockfile>>> {
+ self
+ .maybe_config_file_info
+ .as_ref()
+ .and_then(|c| c.maybe_lockfile.as_ref())
+ }
+
+ pub fn clear_config_file(&mut self) {
+ self.maybe_config_file_info = None;
+ }
+
+ pub fn set_config_file(&mut self, config_file: ConfigFile) {
+ self.maybe_config_file_info = Some(LspConfigFileInfo {
+ maybe_lockfile: resolve_lockfile_from_config(&config_file),
+ maybe_node_modules_dir: resolve_node_modules_dir(&config_file),
+ config_file,
+ });
+ }
+
pub fn workspace_settings(&self) -> &WorkspaceSettings {
&self.settings.workspace
}
@@ -662,6 +712,48 @@ impl Config {
}
}
+fn resolve_lockfile_from_config(
+ config_file: &ConfigFile,
+) -> Option<Arc<Mutex<Lockfile>>> {
+ let lockfile_path = match config_file.resolve_lockfile_path() {
+ Ok(Some(value)) => value,
+ Ok(None) => return None,
+ Err(err) => {
+ lsp_warn!("Error resolving lockfile: {:#}", err);
+ return None;
+ }
+ };
+ resolve_lockfile_from_path(lockfile_path)
+}
+
+fn resolve_node_modules_dir(config_file: &ConfigFile) -> Option<PathBuf> {
+ // For the language server, require an explicit opt-in via the
+ // `nodeModulesDir: true` setting in the deno.json file. This is to
+ // reduce the chance of modifying someone's node_modules directory
+ // without them having asked us to do so.
+ if config_file.node_modules_dir() != Some(true) {
+ return None;
+ }
+ if config_file.specifier.scheme() != "file" {
+ return None;
+ }
+ let file_path = config_file.specifier.to_file_path().ok()?;
+ let node_modules_dir = file_path.parent()?.join("node_modules");
+ canonicalize_path_maybe_not_exists(&node_modules_dir).ok()
+}
+
+fn resolve_lockfile_from_path(
+ lockfile_path: PathBuf,
+) -> Option<Arc<Mutex<Lockfile>>> {
+ match Lockfile::new(lockfile_path, false) {
+ Ok(value) => Some(Arc::new(Mutex::new(value))),
+ Err(err) => {
+ lsp_warn!("Error loading lockfile: {:#}", err);
+ None
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;