mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
refactor(lsp): move config file related code to config.rs (#19790)
Will make #19788 easier.
This commit is contained in:
parent
629d09b149
commit
8dd9d5f523
10 changed files with 176 additions and 169 deletions
6
cli/cache/common.rs
vendored
6
cli/cache/common.rs
vendored
|
@ -11,6 +11,10 @@ impl FastInsecureHasher {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash(hashable: impl std::hash::Hash) -> u64 {
|
||||||
|
Self::new().write_hashable(hashable).finish()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_str(&mut self, text: &str) -> &mut Self {
|
pub fn write_str(&mut self, text: &str) -> &mut Self {
|
||||||
self.write(text.as_bytes());
|
self.write(text.as_bytes());
|
||||||
self
|
self
|
||||||
|
@ -33,7 +37,7 @@ impl FastInsecureHasher {
|
||||||
|
|
||||||
pub fn write_hashable(
|
pub fn write_hashable(
|
||||||
&mut self,
|
&mut self,
|
||||||
hashable: &impl std::hash::Hash,
|
hashable: impl std::hash::Hash,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
hashable.hash(&mut self.0);
|
hashable.hash(&mut self.0);
|
||||||
self
|
self
|
||||||
|
|
13
cli/cache/incremental.rs
vendored
13
cli/cache/incremental.rs
vendored
|
@ -72,9 +72,8 @@ impl IncrementalCacheInner {
|
||||||
state: &TState,
|
state: &TState,
|
||||||
initial_file_paths: &[PathBuf],
|
initial_file_paths: &[PathBuf],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let state_hash = FastInsecureHasher::new()
|
let state_hash =
|
||||||
.write_str(&serde_json::to_string(state).unwrap())
|
FastInsecureHasher::hash(serde_json::to_string(state).unwrap());
|
||||||
.finish();
|
|
||||||
let sql_cache = SqlIncrementalCache::new(db, state_hash);
|
let sql_cache = SqlIncrementalCache::new(db, state_hash);
|
||||||
Self::from_sql_incremental_cache(sql_cache, initial_file_paths)
|
Self::from_sql_incremental_cache(sql_cache, initial_file_paths)
|
||||||
}
|
}
|
||||||
|
@ -114,15 +113,13 @@ impl IncrementalCacheInner {
|
||||||
|
|
||||||
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
||||||
match self.previous_hashes.get(file_path) {
|
match self.previous_hashes.get(file_path) {
|
||||||
Some(hash) => {
|
Some(hash) => *hash == FastInsecureHasher::hash(file_text),
|
||||||
*hash == FastInsecureHasher::new().write_str(file_text).finish()
|
|
||||||
}
|
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_file(&self, file_path: &Path, file_text: &str) {
|
pub fn update_file(&self, file_path: &Path, file_text: &str) {
|
||||||
let hash = FastInsecureHasher::new().write_str(file_text).finish();
|
let hash = FastInsecureHasher::hash(file_text);
|
||||||
if let Some(previous_hash) = self.previous_hashes.get(file_path) {
|
if let Some(previous_hash) = self.previous_hashes.get(file_path) {
|
||||||
if *previous_hash == hash {
|
if *previous_hash == hash {
|
||||||
return; // do not bother updating the db file because nothing has changed
|
return; // do not bother updating the db file because nothing has changed
|
||||||
|
@ -270,7 +267,7 @@ mod test {
|
||||||
let sql_cache = SqlIncrementalCache::new(conn, 1);
|
let sql_cache = SqlIncrementalCache::new(conn, 1);
|
||||||
let file_path = PathBuf::from("/mod.ts");
|
let file_path = PathBuf::from("/mod.ts");
|
||||||
let file_text = "test";
|
let file_text = "test";
|
||||||
let file_hash = FastInsecureHasher::new().write_str(file_text).finish();
|
let file_hash = FastInsecureHasher::hash(file_text);
|
||||||
sql_cache.set_source_hash(&file_path, file_hash).unwrap();
|
sql_cache.set_source_hash(&file_path, file_hash).unwrap();
|
||||||
let cache = IncrementalCacheInner::from_sql_incremental_cache(
|
let cache = IncrementalCacheInner::from_sql_incremental_cache(
|
||||||
sql_cache,
|
sql_cache,
|
||||||
|
|
5
cli/cache/node.rs
vendored
5
cli/cache/node.rs
vendored
|
@ -49,10 +49,7 @@ impl NodeAnalysisCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_source_hash(text: &str) -> String {
|
pub fn compute_source_hash(text: &str) -> String {
|
||||||
FastInsecureHasher::new()
|
FastInsecureHasher::hash(text).to_string()
|
||||||
.write_str(text)
|
|
||||||
.finish()
|
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_ok<T: Default>(res: Result<T, AnyError>) -> T {
|
fn ensure_ok<T: Default>(res: Result<T, AnyError>) -> T {
|
||||||
|
|
2
cli/cache/parsed_source.rs
vendored
2
cli/cache/parsed_source.rs
vendored
|
@ -262,7 +262,7 @@ impl deno_graph::ModuleAnalyzer for ParsedSourceCacheModuleAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_source_hash(bytes: &[u8]) -> String {
|
fn compute_source_hash(bytes: &[u8]) -> String {
|
||||||
FastInsecureHasher::new().write(bytes).finish().to_string()
|
FastInsecureHasher::hash(bytes).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -26,9 +26,7 @@ impl Emitter {
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
emit_options: deno_ast::EmitOptions,
|
emit_options: deno_ast::EmitOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let emit_options_hash = FastInsecureHasher::new()
|
let emit_options_hash = FastInsecureHasher::hash(&emit_options);
|
||||||
.write_hashable(&emit_options)
|
|
||||||
.finish();
|
|
||||||
Self {
|
Self {
|
||||||
emit_cache,
|
emit_cache,
|
||||||
parsed_source_cache,
|
parsed_source_cache,
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use super::logging::lsp_log;
|
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 crate::util::path::specifier_to_file_path;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde::Serialize;
|
use deno_core::serde::Serialize;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_lockfile::Lockfile;
|
||||||
use lsp::Url;
|
use lsp::Url;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
|
@ -427,6 +433,16 @@ pub struct Settings {
|
||||||
pub workspace: WorkspaceSettings,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub client_capabilities: ClientCapabilities,
|
pub client_capabilities: ClientCapabilities,
|
||||||
|
@ -434,6 +450,9 @@ pub struct Config {
|
||||||
pub root_uri: Option<ModuleSpecifier>,
|
pub root_uri: Option<ModuleSpecifier>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
pub workspace_folders: Option<Vec<(ModuleSpecifier, lsp::WorkspaceFolder)>>,
|
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 {
|
impl Config {
|
||||||
|
@ -445,9 +464,40 @@ impl Config {
|
||||||
root_uri: None,
|
root_uri: None,
|
||||||
settings: Default::default(),
|
settings: Default::default(),
|
||||||
workspace_folders: None,
|
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 {
|
pub fn workspace_settings(&self) -> &WorkspaceSettings {
|
||||||
&self.settings.workspace
|
&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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -1192,7 +1192,7 @@ impl Documents {
|
||||||
maybe_package_json_deps: Option<&PackageJsonDeps>,
|
maybe_package_json_deps: Option<&PackageJsonDeps>,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let mut hasher = FastInsecureHasher::default();
|
let mut hasher = FastInsecureHasher::default();
|
||||||
hasher.write_hashable(&document_preload_limit);
|
hasher.write_hashable(document_preload_limit);
|
||||||
hasher.write_hashable(&{
|
hasher.write_hashable(&{
|
||||||
// ensure these are sorted so the hashing is deterministic
|
// ensure these are sorted so the hashing is deterministic
|
||||||
let mut enabled_urls = enabled_urls.to_vec();
|
let mut enabled_urls = enabled_urls.to_vec();
|
||||||
|
@ -1203,7 +1203,7 @@ impl Documents {
|
||||||
hasher.write_str(&import_map.to_json());
|
hasher.write_str(&import_map.to_json());
|
||||||
hasher.write_str(import_map.base_url().as_str());
|
hasher.write_str(import_map.base_url().as_str());
|
||||||
}
|
}
|
||||||
hasher.write_hashable(&maybe_jsx_config);
|
hasher.write_hashable(maybe_jsx_config);
|
||||||
if let Some(package_json_deps) = &maybe_package_json_deps {
|
if let Some(package_json_deps) = &maybe_package_json_deps {
|
||||||
// We need to ensure the hashing is deterministic so explicitly type
|
// We need to ensure the hashing is deterministic so explicitly type
|
||||||
// this in order to catch if the type of package_json_deps ever changes
|
// this in order to catch if the type of package_json_deps ever changes
|
||||||
|
|
|
@ -4,7 +4,6 @@ use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use deno_core::resolve_url;
|
use deno_core::resolve_url;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
|
@ -101,7 +100,6 @@ use crate::npm::NpmCacheDir;
|
||||||
use crate::npm::NpmResolution;
|
use crate::npm::NpmResolution;
|
||||||
use crate::tools::fmt::format_file;
|
use crate::tools::fmt::format_file;
|
||||||
use crate::tools::fmt::format_parsed_source;
|
use crate::tools::fmt::format_parsed_source;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
|
||||||
use crate::util::fs::remove_dir_all_if_exists;
|
use crate::util::fs::remove_dir_all_if_exists;
|
||||||
use crate::util::path::specifier_to_file_path;
|
use crate::util::path::specifier_to_file_path;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
@ -135,51 +133,15 @@ struct LspNpmConfigHash(u64);
|
||||||
impl LspNpmConfigHash {
|
impl LspNpmConfigHash {
|
||||||
pub fn from_inner(inner: &Inner) -> Self {
|
pub fn from_inner(inner: &Inner) -> Self {
|
||||||
let mut hasher = FastInsecureHasher::new();
|
let mut hasher = FastInsecureHasher::new();
|
||||||
hasher.write_hashable(&inner.maybe_node_modules_dir_path());
|
hasher.write_hashable(inner.config.maybe_node_modules_dir_path());
|
||||||
hasher.write_hashable(&inner.maybe_cache_path);
|
hasher.write_hashable(&inner.maybe_cache_path);
|
||||||
hash_lockfile_with_hasher(&mut hasher, inner.maybe_lockfile());
|
if let Some(lockfile) = inner.config.maybe_lockfile() {
|
||||||
|
hasher.write_hashable(&*lockfile.lock());
|
||||||
|
}
|
||||||
Self(hasher.finish())
|
Self(hasher.finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_lockfile(maybe_lockfile: Option<&Arc<Mutex<Lockfile>>>) -> u64 {
|
|
||||||
let mut hasher = FastInsecureHasher::new();
|
|
||||||
hash_lockfile_with_hasher(&mut hasher, maybe_lockfile);
|
|
||||||
hasher.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_lockfile_with_hasher(
|
|
||||||
hasher: &mut FastInsecureHasher,
|
|
||||||
maybe_lockfile: Option<&Arc<Mutex<Lockfile>>>,
|
|
||||||
) {
|
|
||||||
if let Some(lockfile) = &maybe_lockfile {
|
|
||||||
let lockfile = lockfile.lock();
|
|
||||||
hasher.write_hashable(&*lockfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Contains the config file and dependent information.
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct LspConfigFileInfo {
|
|
||||||
config_file: ConfigFile,
|
|
||||||
/// An optional deno.lock file, which is resolved relative to the config file.
|
|
||||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
|
||||||
/// The canonicalized node_modules directory, which is found relative to the config file.
|
|
||||||
maybe_node_modules_dir: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
|
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
|
||||||
|
|
||||||
|
@ -219,9 +181,6 @@ pub struct Inner {
|
||||||
/// An optional path to the DENO_DIR which has been specified in the client
|
/// An optional path to the DENO_DIR which has been specified in the client
|
||||||
/// options.
|
/// options.
|
||||||
maybe_cache_path: Option<PathBuf>,
|
maybe_cache_path: Option<PathBuf>,
|
||||||
/// 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>,
|
|
||||||
/// An optional import map which is used to resolve modules.
|
/// An optional import map which is used to resolve modules.
|
||||||
maybe_import_map: Option<Arc<ImportMap>>,
|
maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
/// The URL for the import map which is used to determine relative imports.
|
/// The URL for the import map which is used to determine relative imports.
|
||||||
|
@ -520,22 +479,6 @@ impl LanguageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 create_npm_api_and_cache(
|
fn create_npm_api_and_cache(
|
||||||
dir: &DenoDir,
|
dir: &DenoDir,
|
||||||
http_client: Arc<HttpClient>,
|
http_client: Arc<HttpClient>,
|
||||||
|
@ -651,7 +594,6 @@ impl Inner {
|
||||||
documents,
|
documents,
|
||||||
http_client,
|
http_client,
|
||||||
maybe_cache_path: None,
|
maybe_cache_path: None,
|
||||||
maybe_config_file_info: None,
|
|
||||||
maybe_import_map: None,
|
maybe_import_map: None,
|
||||||
maybe_import_map_uri: None,
|
maybe_import_map_uri: None,
|
||||||
maybe_package_json: None,
|
maybe_package_json: None,
|
||||||
|
@ -836,7 +778,7 @@ impl Inner {
|
||||||
&self,
|
&self,
|
||||||
tsconfig: &mut TsConfig,
|
tsconfig: &mut TsConfig,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
if let Some(config_file) = self.maybe_config_file() {
|
if let Some(config_file) = self.config.maybe_config_file() {
|
||||||
let (value, maybe_ignored_options) = config_file.to_compiler_options()?;
|
let (value, maybe_ignored_options) = config_file.to_compiler_options()?;
|
||||||
tsconfig.merge(&value);
|
tsconfig.merge(&value);
|
||||||
if let Some(ignored_options) = maybe_ignored_options {
|
if let Some(ignored_options) = maybe_ignored_options {
|
||||||
|
@ -854,7 +796,7 @@ impl Inner {
|
||||||
let npm_resolution = Arc::new(NpmResolution::new(
|
let npm_resolution = Arc::new(NpmResolution::new(
|
||||||
self.npm.api.clone(),
|
self.npm.api.clone(),
|
||||||
self.npm.resolution.snapshot(),
|
self.npm.resolution.snapshot(),
|
||||||
self.maybe_lockfile().cloned(),
|
self.config.maybe_lockfile().cloned(),
|
||||||
));
|
));
|
||||||
let node_fs = Arc::new(deno_fs::RealFs);
|
let node_fs = Arc::new(deno_fs::RealFs);
|
||||||
let npm_resolver = Arc::new(CliNpmResolver::new(
|
let npm_resolver = Arc::new(CliNpmResolver::new(
|
||||||
|
@ -866,10 +808,10 @@ impl Inner {
|
||||||
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
&ProgressBar::new(ProgressBarStyle::TextOnly),
|
||||||
self.npm.api.base_url().clone(),
|
self.npm.api.base_url().clone(),
|
||||||
npm_resolution,
|
npm_resolution,
|
||||||
self.maybe_node_modules_dir_path().cloned(),
|
self.config.maybe_node_modules_dir_path().cloned(),
|
||||||
NpmSystemInfo::default(),
|
NpmSystemInfo::default(),
|
||||||
),
|
),
|
||||||
self.maybe_lockfile().cloned(),
|
self.config.maybe_lockfile().cloned(),
|
||||||
));
|
));
|
||||||
let node_resolver =
|
let node_resolver =
|
||||||
Arc::new(NodeResolver::new(node_fs, npm_resolver.clone()));
|
Arc::new(NodeResolver::new(node_fs, npm_resolver.clone()));
|
||||||
|
@ -980,7 +922,7 @@ impl Inner {
|
||||||
registry_url,
|
registry_url,
|
||||||
&progress_bar,
|
&progress_bar,
|
||||||
);
|
);
|
||||||
let maybe_snapshot = match self.maybe_lockfile() {
|
let maybe_snapshot = match self.config.maybe_lockfile() {
|
||||||
Some(lockfile) => {
|
Some(lockfile) => {
|
||||||
match snapshot_from_lockfile(lockfile.clone(), &self.npm.api).await {
|
match snapshot_from_lockfile(lockfile.clone(), &self.npm.api).await {
|
||||||
Ok(snapshot) => Some(snapshot),
|
Ok(snapshot) => Some(snapshot),
|
||||||
|
@ -998,7 +940,7 @@ impl Inner {
|
||||||
progress_bar,
|
progress_bar,
|
||||||
self.npm.api.clone(),
|
self.npm.api.clone(),
|
||||||
self.npm.cache.clone(),
|
self.npm.cache.clone(),
|
||||||
self.maybe_node_modules_dir_path().cloned(),
|
self.config.maybe_node_modules_dir_path().cloned(),
|
||||||
maybe_snapshot,
|
maybe_snapshot,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1035,7 +977,7 @@ impl Inner {
|
||||||
) -> Result<ImportMap, AnyError> {
|
) -> Result<ImportMap, AnyError> {
|
||||||
resolve_import_map_from_specifier(
|
resolve_import_map_from_specifier(
|
||||||
import_map_url,
|
import_map_url,
|
||||||
self.maybe_config_file(),
|
self.config.maybe_config_file(),
|
||||||
&self.create_file_fetcher(cache_setting),
|
&self.create_file_fetcher(cache_setting),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -1076,7 +1018,7 @@ impl Inner {
|
||||||
"Setting import map from workspace settings: \"{}\"",
|
"Setting import map from workspace settings: \"{}\"",
|
||||||
import_map_str
|
import_map_str
|
||||||
);
|
);
|
||||||
if let Some(config_file) = self.maybe_config_file() {
|
if let Some(config_file) = self.config.maybe_config_file() {
|
||||||
if let Some(import_map_path) = config_file.to_import_map_path() {
|
if let Some(import_map_path) = config_file.to_import_map_path() {
|
||||||
lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier);
|
lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier);
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1044,7 @@ impl Inner {
|
||||||
import_map_str
|
import_map_str
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if let Some(config_file) = self.maybe_config_file() {
|
} else if let Some(config_file) = self.config.maybe_config_file() {
|
||||||
if config_file.is_an_import_map() {
|
if config_file.is_an_import_map() {
|
||||||
lsp_log!(
|
lsp_log!(
|
||||||
"Setting import map defined in configuration file: \"{}\"",
|
"Setting import map defined in configuration file: \"{}\"",
|
||||||
|
@ -1165,7 +1107,7 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_config_file(&mut self) -> Result<(), AnyError> {
|
async fn update_config_file(&mut self) -> Result<(), AnyError> {
|
||||||
self.maybe_config_file_info = None;
|
self.config.clear_config_file();
|
||||||
self.fmt_options = Default::default();
|
self.fmt_options = Default::default();
|
||||||
self.lint_options = Default::default();
|
self.lint_options = Default::default();
|
||||||
if let Some(config_file) = self.get_config_file()? {
|
if let Some(config_file) = self.get_config_file()? {
|
||||||
|
@ -1186,11 +1128,7 @@ impl Inner {
|
||||||
anyhow!("Unable to update formatter configuration: {:?}", err)
|
anyhow!("Unable to update formatter configuration: {:?}", err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.maybe_config_file_info = Some(LspConfigFileInfo {
|
self.config.set_config_file(config_file);
|
||||||
maybe_lockfile: self.resolve_lockfile_from_config(&config_file),
|
|
||||||
maybe_node_modules_dir: resolve_node_modules_dir(&config_file),
|
|
||||||
config_file,
|
|
||||||
});
|
|
||||||
self.lint_options = lint_options;
|
self.lint_options = lint_options;
|
||||||
self.fmt_options = fmt_options;
|
self.fmt_options = fmt_options;
|
||||||
}
|
}
|
||||||
|
@ -1198,45 +1136,12 @@ impl Inner {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_lockfile_from_config(
|
|
||||||
&self,
|
|
||||||
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 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())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_config_file(&self) -> Option<&ConfigFile> {
|
|
||||||
self.maybe_config_file_info.as_ref().map(|c| &c.config_file)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_lockfile(&self) -> Option<&Arc<Mutex<Lockfile>>> {
|
|
||||||
self
|
|
||||||
.maybe_config_file_info
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|c| c.maybe_lockfile.as_ref())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the package.json. Always ensure this is done after updating
|
/// Updates the package.json. Always ensure this is done after updating
|
||||||
/// the configuration file as the resolution of this depends on that.
|
/// the configuration file as the resolution of this depends on that.
|
||||||
fn update_package_json(&mut self) -> Result<(), AnyError> {
|
fn update_package_json(&mut self) -> Result<(), AnyError> {
|
||||||
self.maybe_package_json = None;
|
self.maybe_package_json = None;
|
||||||
self.maybe_package_json =
|
self.maybe_package_json =
|
||||||
self.get_package_json(self.maybe_config_file())?;
|
self.get_package_json(self.config.maybe_config_file())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1393,10 +1298,7 @@ impl Inner {
|
||||||
.workspace_settings()
|
.workspace_settings()
|
||||||
.document_preload_limit,
|
.document_preload_limit,
|
||||||
maybe_import_map: self.maybe_import_map.clone(),
|
maybe_import_map: self.maybe_import_map.clone(),
|
||||||
maybe_config_file: self
|
maybe_config_file: self.config.maybe_config_file(),
|
||||||
.maybe_config_file_info
|
|
||||||
.as_ref()
|
|
||||||
.map(|c| &c.config_file),
|
|
||||||
maybe_package_json: self.maybe_package_json.as_ref(),
|
maybe_package_json: self.maybe_package_json.as_ref(),
|
||||||
npm_registry_api: self.npm.api.clone(),
|
npm_registry_api: self.npm.api.clone(),
|
||||||
npm_resolution: self.npm.resolution.clone(),
|
npm_resolution: self.npm.resolution.clone(),
|
||||||
|
@ -1556,6 +1458,30 @@ impl Inner {
|
||||||
&mut self,
|
&mut self,
|
||||||
params: DidChangeWatchedFilesParams,
|
params: DidChangeWatchedFilesParams,
|
||||||
) {
|
) {
|
||||||
|
fn has_lockfile_changed(
|
||||||
|
lockfile: &Lockfile,
|
||||||
|
changed_urls: &HashSet<Url>,
|
||||||
|
) -> bool {
|
||||||
|
let lockfile_path = lockfile.filename.clone();
|
||||||
|
let Ok(specifier) = ModuleSpecifier::from_file_path(&lockfile_path) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if !changed_urls.contains(&specifier) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
match Lockfile::new(lockfile_path, false) {
|
||||||
|
Ok(new_lockfile) => {
|
||||||
|
// only update if the lockfile has changed
|
||||||
|
FastInsecureHasher::hash(lockfile)
|
||||||
|
!= FastInsecureHasher::hash(new_lockfile)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
lsp_warn!("Error loading lockfile: {:#}", err);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mark = self
|
let mark = self
|
||||||
.performance
|
.performance
|
||||||
.mark("did_change_watched_files", Some(¶ms));
|
.mark("did_change_watched_files", Some(¶ms));
|
||||||
|
@ -1567,8 +1493,14 @@ impl Inner {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// if the current deno.json has changed, we need to reload it
|
// if the current deno.json has changed, we need to reload it
|
||||||
if let Some(config_file) = self.maybe_config_file() {
|
if let Some(config_file) = self.config.maybe_config_file() {
|
||||||
if changes.contains(&config_file.specifier) {
|
if changes.contains(&config_file.specifier)
|
||||||
|
|| self
|
||||||
|
.config
|
||||||
|
.maybe_lockfile()
|
||||||
|
.map(|l| has_lockfile_changed(&l.lock(), &changes))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
if let Err(err) = self.update_config_file().await {
|
if let Err(err) = self.update_config_file().await {
|
||||||
self.client.show_message(MessageType::WARNING, err);
|
self.client.show_message(MessageType::WARNING, err);
|
||||||
}
|
}
|
||||||
|
@ -1579,25 +1511,6 @@ impl Inner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(config_info) = self.maybe_config_file_info.as_mut() {
|
|
||||||
if let Some(lockfile) = config_info.maybe_lockfile.as_ref() {
|
|
||||||
let lockfile_path = lockfile.lock().filename.clone();
|
|
||||||
let maybe_specifier =
|
|
||||||
ModuleSpecifier::from_file_path(&lockfile_path).ok();
|
|
||||||
if let Some(specifier) = maybe_specifier {
|
|
||||||
if changes.contains(&specifier) {
|
|
||||||
let lockfile_hash = hash_lockfile(Some(lockfile));
|
|
||||||
let new_lockfile = resolve_lockfile_from_path(lockfile_path);
|
|
||||||
// only update if the lockfile has changed
|
|
||||||
if lockfile_hash != hash_lockfile(new_lockfile.as_ref()) {
|
|
||||||
config_info.maybe_lockfile = new_lockfile;
|
|
||||||
touched = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(package_json) = &self.maybe_package_json {
|
if let Some(package_json) = &self.maybe_package_json {
|
||||||
// always update the package json if the deno config changes
|
// always update the package json if the deno config changes
|
||||||
if touched || changes.contains(&package_json.specifier()) {
|
if touched || changes.contains(&package_json.specifier()) {
|
||||||
|
@ -3424,14 +3337,16 @@ impl Inner {
|
||||||
unsafely_ignore_certificate_errors: workspace_settings
|
unsafely_ignore_certificate_errors: workspace_settings
|
||||||
.unsafely_ignore_certificate_errors
|
.unsafely_ignore_certificate_errors
|
||||||
.clone(),
|
.clone(),
|
||||||
node_modules_dir: Some(self.maybe_node_modules_dir_path().is_some()),
|
node_modules_dir: Some(
|
||||||
|
self.config.maybe_node_modules_dir_path().is_some(),
|
||||||
|
),
|
||||||
// bit of a hack to force the lsp to cache the @types/node package
|
// bit of a hack to force the lsp to cache the @types/node package
|
||||||
type_check_mode: crate::args::TypeCheckMode::Local,
|
type_check_mode: crate::args::TypeCheckMode::Local,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
std::env::current_dir().with_context(|| "Failed getting cwd.")?,
|
std::env::current_dir().with_context(|| "Failed getting cwd.")?,
|
||||||
self.maybe_config_file().cloned(),
|
self.config.maybe_config_file().cloned(),
|
||||||
self.maybe_lockfile().cloned(),
|
self.config.maybe_lockfile().cloned(),
|
||||||
self.maybe_package_json.clone(),
|
self.maybe_package_json.clone(),
|
||||||
)?;
|
)?;
|
||||||
cli_options.set_import_map_specifier(self.maybe_import_map_uri.clone());
|
cli_options.set_import_map_specifier(self.maybe_import_map_uri.clone());
|
||||||
|
@ -3464,7 +3379,12 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tasks(&self) -> LspResult<Option<Value>> {
|
fn get_tasks(&self) -> LspResult<Option<Value>> {
|
||||||
Ok(self.maybe_config_file().and_then(|cf| cf.to_lsp_tasks()))
|
Ok(
|
||||||
|
self
|
||||||
|
.config
|
||||||
|
.maybe_config_file()
|
||||||
|
.and_then(|cf| cf.to_lsp_tasks()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inlay_hint(
|
async fn inlay_hint(
|
||||||
|
|
|
@ -120,12 +120,10 @@ impl TypeChecker {
|
||||||
// to make tsc build info work, we need to consistently hash modules, so that
|
// to make tsc build info work, we need to consistently hash modules, so that
|
||||||
// tsc can better determine if an emit is still valid or not, so we provide
|
// tsc can better determine if an emit is still valid or not, so we provide
|
||||||
// that data here.
|
// that data here.
|
||||||
let hash_data = {
|
let hash_data = FastInsecureHasher::new()
|
||||||
let mut hasher = FastInsecureHasher::new();
|
.write(&ts_config.as_bytes())
|
||||||
hasher.write(&ts_config.as_bytes());
|
.write_str(version::deno())
|
||||||
hasher.write_str(version::deno());
|
.finish();
|
||||||
hasher.finish()
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = tsc::exec(tsc::Request {
|
let response = tsc::exec(tsc::Request {
|
||||||
config: ts_config,
|
config: ts_config,
|
||||||
|
|
|
@ -242,10 +242,11 @@ fn get_maybe_hash(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hash(source: &str, hash_data: u64) -> String {
|
fn get_hash(source: &str, hash_data: u64) -> String {
|
||||||
let mut hasher = FastInsecureHasher::new();
|
FastInsecureHasher::new()
|
||||||
hasher.write_str(source);
|
.write_str(source)
|
||||||
hasher.write_u64(hash_data);
|
.write_u64(hash_data)
|
||||||
hasher.finish().to_string()
|
.finish()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hash the URL so it can be sent to `tsc` in a supportable way
|
/// Hash the URL so it can be sent to `tsc` in a supportable way
|
||||||
|
|
Loading…
Reference in a new issue