1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

refactor(lsp): cleanup document preload (#20520)

This commit is contained in:
Nayeem Rahman 2023-09-18 20:58:16 +01:00 committed by GitHub
parent 86c04f43e0
commit f5963b6a05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 144 deletions

View file

@ -4,7 +4,6 @@ use super::logging::lsp_log;
use crate::args::ConfigFile; use crate::args::ConfigFile;
use crate::lsp::logging::lsp_warn; use crate::lsp::logging::lsp_warn;
use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::util::path::specifier_from_file_path;
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::parking_lot::Mutex;
@ -645,77 +644,44 @@ impl Config {
true true
} }
/// Gets the directories or specifically enabled file paths based on the pub fn get_enabled_paths(&self) -> Vec<PathBuf> {
/// workspace config. let mut paths = vec![];
///
/// WARNING: This may incorrectly have some directory urls as being
/// represented as file urls.
pub fn enabled_urls(&self) -> Vec<Url> {
let mut urls = vec![];
for (workspace_uri, _) in &self.workspace_folders { for (workspace_uri, _) in &self.workspace_folders {
let Ok(workspace_path) = specifier_to_file_path(workspace_uri) else { let Ok(workspace_path) = specifier_to_file_path(workspace_uri) else {
lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri); lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri);
continue; continue;
}; };
let specifier_settings = self.settings.specifiers.get(workspace_uri); let specifier_settings = self.settings.specifiers.get(workspace_uri);
let enable = specifier_settings
.and_then(|s| s.enable)
.or(self.settings.workspace.enable)
.unwrap_or(self.has_config_file());
let disable_paths = specifier_settings
.map(|s| &s.disable_paths)
.unwrap_or(&self.settings.workspace.disable_paths);
let resolved_disable_paths = disable_paths
.iter()
.map(|p| workspace_path.join(p))
.collect::<Vec<_>>();
let enable_paths = specifier_settings let enable_paths = specifier_settings
.and_then(|s| s.enable_paths.as_ref()) .and_then(|s| s.enable_paths.as_ref())
.or(self.settings.workspace.enable_paths.as_ref()); .or(self.settings.workspace.enable_paths.as_ref());
if let Some(enable_paths) = enable_paths { if let Some(enable_paths) = enable_paths {
for path in enable_paths { for path in enable_paths {
let path = workspace_path.join(path); paths.push(workspace_path.join(path));
let Ok(path_uri) = specifier_from_file_path(&path) else {
lsp_log!("Unable to convert path \"{}\" to uri.", path.display());
continue;
};
if !resolved_disable_paths.iter().any(|p| path.starts_with(p)) {
urls.push(path_uri);
}
} }
} else if enable } else {
&& !resolved_disable_paths paths.push(workspace_path);
.iter()
.any(|p| workspace_path.starts_with(p))
{
urls.push(workspace_uri.clone());
} }
} }
paths.sort();
// sort for determinism paths.dedup();
urls.sort(); paths
urls.dedup();
urls
} }
pub fn disabled_urls(&self) -> Vec<Url> { pub fn get_disabled_paths(&self) -> Vec<PathBuf> {
let mut paths = vec![];
if let Some(cf) = self.maybe_config_file() {
if let Some(files) = cf.to_files_config().ok().flatten() {
for path in files.exclude {
paths.push(path);
}
}
}
let root_enable = self let root_enable = self
.settings .settings
.workspace .workspace
.enable .enable
.unwrap_or(self.has_config_file()); .unwrap_or(self.has_config_file());
let mut urls = vec![];
if let Some(cf) = self.maybe_config_file() {
if let Some(files) = cf.to_files_config().ok().flatten() {
for path in files.exclude {
let Ok(path_uri) = specifier_from_file_path(&path) else {
lsp_log!("Unable to convert path \"{}\" to uri.", path.display());
continue;
};
urls.push(path_uri);
}
}
}
for (workspace_uri, _) in &self.workspace_folders { for (workspace_uri, _) in &self.workspace_folders {
let Ok(workspace_path) = specifier_to_file_path(workspace_uri) else { let Ok(workspace_path) = specifier_to_file_path(workspace_uri) else {
lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri); lsp_log!("Unable to convert uri \"{}\" to path.", workspace_uri);
@ -730,20 +696,15 @@ impl Config {
.map(|s| &s.disable_paths) .map(|s| &s.disable_paths)
.unwrap_or(&self.settings.workspace.disable_paths); .unwrap_or(&self.settings.workspace.disable_paths);
for path in disable_paths { for path in disable_paths {
let path = workspace_path.join(path); paths.push(workspace_path.join(path));
let Ok(path_uri) = specifier_from_file_path(&path) else {
lsp_log!("Unable to convert path \"{}\" to uri.", path.display());
continue;
};
urls.push(path_uri);
} }
} else { } else {
urls.push(workspace_uri.clone()); paths.push(workspace_path);
} }
} }
urls.sort(); paths.sort();
urls.dedup(); paths.dedup();
urls paths
} }
pub fn specifier_code_lens_test(&self, specifier: &ModuleSpecifier) -> bool { pub fn specifier_code_lens_test(&self, specifier: &ModuleSpecifier) -> bool {
@ -1129,45 +1090,33 @@ mod tests {
} }
#[test] #[test]
fn config_enabled_urls() { fn config_get_enabled_paths() {
let root_dir = resolve_url("file:///example/").unwrap(); let mut config = Config::new();
let mut config = Config::new_with_root(root_dir.clone());
config.settings.workspace.enable = Some(false);
config.settings.workspace.enable_paths = None;
assert_eq!(config.enabled_urls(), vec![]);
config.settings.workspace.enable = Some(true);
assert_eq!(config.enabled_urls(), vec![root_dir]);
config.settings.workspace.enable = Some(false);
let root_dir1 = Url::parse("file:///root1/").unwrap();
let root_dir2 = Url::parse("file:///root2/").unwrap();
let root_dir3 = Url::parse("file:///root3/").unwrap();
config.workspace_folders = vec![ config.workspace_folders = vec![
( (
root_dir1.clone(), Url::parse("file:///root1/").unwrap(),
lsp::WorkspaceFolder { lsp::WorkspaceFolder {
uri: root_dir1.clone(), uri: Url::parse("file:///root1/").unwrap(),
name: "1".to_string(), name: "1".to_string(),
}, },
), ),
( (
root_dir2.clone(), Url::parse("file:///root2/").unwrap(),
lsp::WorkspaceFolder { lsp::WorkspaceFolder {
uri: root_dir2.clone(), uri: Url::parse("file:///root2/").unwrap(),
name: "2".to_string(), name: "2".to_string(),
}, },
), ),
( (
root_dir3.clone(), Url::parse("file:///root3/").unwrap(),
lsp::WorkspaceFolder { lsp::WorkspaceFolder {
uri: root_dir3.clone(), uri: Url::parse("file:///root3/").unwrap(),
name: "3".to_string(), name: "3".to_string(),
}, },
), ),
]; ];
config.set_specifier_settings( config.set_specifier_settings(
root_dir1.clone(), Url::parse("file:///root1/").unwrap(),
SpecifierSettings { SpecifierSettings {
enable_paths: Some(vec![ enable_paths: Some(vec![
"sub_dir".to_string(), "sub_dir".to_string(),
@ -1178,14 +1127,14 @@ mod tests {
}, },
); );
config.set_specifier_settings( config.set_specifier_settings(
root_dir2.clone(), Url::parse("file:///root2/").unwrap(),
SpecifierSettings { SpecifierSettings {
enable_paths: Some(vec!["other.ts".to_string()]), enable_paths: Some(vec!["other.ts".to_string()]),
..Default::default() ..Default::default()
}, },
); );
config.set_specifier_settings( config.set_specifier_settings(
root_dir3.clone(), Url::parse("file:///root3/").unwrap(),
SpecifierSettings { SpecifierSettings {
enable: Some(true), enable: Some(true),
..Default::default() ..Default::default()
@ -1193,13 +1142,13 @@ mod tests {
); );
assert_eq!( assert_eq!(
config.enabled_urls(), config.get_enabled_paths(),
vec![ vec![
root_dir1.join("sub_dir").unwrap(), PathBuf::from("/root1/sub_dir"),
root_dir1.join("sub_dir/other").unwrap(), PathBuf::from("/root1/sub_dir/other"),
root_dir1.join("test.ts").unwrap(), PathBuf::from("/root1/test.ts"),
root_dir2.join("other.ts").unwrap(), PathBuf::from("/root2/other.ts"),
root_dir3 PathBuf::from("/root3/"),
] ]
); );
} }
@ -1209,12 +1158,12 @@ mod tests {
let root_uri = resolve_url("file:///root/").unwrap(); let root_uri = resolve_url("file:///root/").unwrap();
let mut config = Config::new_with_root(root_uri.clone()); let mut config = Config::new_with_root(root_uri.clone());
config.settings.workspace.enable = None; config.settings.workspace.enable = None;
assert_eq!(config.enabled_urls(), vec![]); assert!(!config.specifier_enabled(&root_uri));
config.set_config_file( config.set_config_file(
ConfigFile::new("{}", root_uri.join("deno.json").unwrap()).unwrap(), ConfigFile::new("{}", root_uri.join("deno.json").unwrap()).unwrap(),
); );
assert_eq!(config.enabled_urls(), vec![root_uri]); assert!(config.specifier_enabled(&root_uri));
} }
// Regression test for https://github.com/denoland/vscode_deno/issues/917. // Regression test for https://github.com/denoland/vscode_deno/issues/917.

View file

@ -803,8 +803,8 @@ impl FileSystemDocuments {
} }
pub struct UpdateDocumentConfigOptions<'a> { pub struct UpdateDocumentConfigOptions<'a> {
pub enabled_urls: Vec<Url>, pub enabled_paths: Vec<PathBuf>,
pub disabled_urls: Vec<Url>, pub disabled_paths: Vec<PathBuf>,
pub document_preload_limit: usize, pub document_preload_limit: usize,
pub maybe_import_map: Option<Arc<import_map::ImportMap>>, pub maybe_import_map: Option<Arc<import_map::ImportMap>>,
pub maybe_config_file: Option<&'a ConfigFile>, pub maybe_config_file: Option<&'a ConfigFile>,
@ -1183,7 +1183,7 @@ impl Documents {
pub fn update_config(&mut self, options: UpdateDocumentConfigOptions) { pub fn update_config(&mut self, options: UpdateDocumentConfigOptions) {
fn calculate_resolver_config_hash( fn calculate_resolver_config_hash(
enabled_urls: &[Url], enabled_paths: &[PathBuf],
document_preload_limit: usize, document_preload_limit: usize,
maybe_import_map: Option<&import_map::ImportMap>, maybe_import_map: Option<&import_map::ImportMap>,
maybe_jsx_config: Option<&JsxImportSourceConfig>, maybe_jsx_config: Option<&JsxImportSourceConfig>,
@ -1194,9 +1194,9 @@ impl Documents {
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_paths = enabled_paths.to_vec();
enabled_urls.sort_unstable(); enabled_paths.sort_unstable();
enabled_urls enabled_paths
}); });
if let Some(import_map) = maybe_import_map { if let Some(import_map) = maybe_import_map {
hasher.write_str(&import_map.to_json()); hasher.write_str(&import_map.to_json());
@ -1233,7 +1233,7 @@ impl Documents {
.maybe_config_file .maybe_config_file
.and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten()); .and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten());
let new_resolver_config_hash = calculate_resolver_config_hash( let new_resolver_config_hash = calculate_resolver_config_hash(
&options.enabled_urls, &options.enabled_paths,
options.document_preload_limit, options.document_preload_limit,
options.maybe_import_map.as_deref(), options.maybe_import_map.as_deref(),
maybe_jsx_config.as_ref(), maybe_jsx_config.as_ref(),
@ -1278,16 +1278,8 @@ impl Documents {
// only refresh the dependencies if the underlying configuration has changed // only refresh the dependencies if the underlying configuration has changed
if self.resolver_config_hash != new_resolver_config_hash { if self.resolver_config_hash != new_resolver_config_hash {
self.refresh_dependencies( self.refresh_dependencies(
options options.enabled_paths,
.enabled_urls options.disabled_paths,
.iter()
.filter_map(|url| specifier_to_file_path(url).ok())
.collect(),
options
.disabled_urls
.iter()
.filter_map(|url| specifier_to_file_path(url).ok())
.collect(),
options.document_preload_limit, options.document_preload_limit,
); );
self.resolver_config_hash = new_resolver_config_hash; self.resolver_config_hash = new_resolver_config_hash;
@ -1710,14 +1702,18 @@ impl PreloadDocumentFinder {
// initialize the finder with the initial paths // initialize the finder with the initial paths
let mut dirs = Vec::with_capacity(options.enabled_paths.len()); let mut dirs = Vec::with_capacity(options.enabled_paths.len());
for path in options.enabled_paths { for path in options.enabled_paths {
if path.is_dir() { if !finder.disabled_paths.contains(&path)
if is_allowed_root_dir(&path) { && !finder.disabled_globs.matches_path(&path)
dirs.push(path); {
if path.is_dir() {
if is_allowed_root_dir(&path) {
dirs.push(path);
}
} else {
finder
.pending_entries
.push_back(PendingEntry::SpecifiedRootFile(path));
} }
} else {
finder
.pending_entries
.push_back(PendingEntry::SpecifiedRootFile(path));
} }
} }
for dir in sort_and_remove_non_leaf_dirs(dirs) { for dir in sort_and_remove_non_leaf_dirs(dirs) {
@ -2028,8 +2024,8 @@ console.log(b, "hello deno");
.unwrap(); .unwrap();
documents.update_config(UpdateDocumentConfigOptions { documents.update_config(UpdateDocumentConfigOptions {
enabled_urls: vec![], enabled_paths: vec![],
disabled_urls: vec![], disabled_paths: vec![],
document_preload_limit: 1_000, document_preload_limit: 1_000,
maybe_import_map: Some(Arc::new(import_map)), maybe_import_map: Some(Arc::new(import_map)),
maybe_config_file: None, maybe_config_file: None,
@ -2070,8 +2066,8 @@ console.log(b, "hello deno");
.unwrap(); .unwrap();
documents.update_config(UpdateDocumentConfigOptions { documents.update_config(UpdateDocumentConfigOptions {
enabled_urls: vec![], enabled_paths: vec![],
disabled_urls: vec![], disabled_paths: vec![],
document_preload_limit: 1_000, document_preload_limit: 1_000,
maybe_import_map: Some(Arc::new(import_map)), maybe_import_map: Some(Arc::new(import_map)),
maybe_config_file: None, maybe_config_file: None,

View file

@ -1353,8 +1353,8 @@ impl Inner {
async fn refresh_documents_config(&mut self) { async fn refresh_documents_config(&mut self) {
self.documents.update_config(UpdateDocumentConfigOptions { self.documents.update_config(UpdateDocumentConfigOptions {
enabled_urls: self.config.enabled_urls(), enabled_paths: self.config.get_enabled_paths(),
disabled_urls: self.config.disabled_urls(), disabled_paths: self.config.get_disabled_paths(),
document_preload_limit: self document_preload_limit: self
.config .config
.workspace_settings() .workspace_settings()

View file

@ -122,28 +122,6 @@ pub fn specifier_to_file_path(
} }
} }
/// Attempts to convert a file path to a specifier. By default, uses the Url
/// crate's `from_file_path()` method, but falls back to try and resolve
/// unix-style paths on Windows.
pub fn specifier_from_file_path(
path: &Path,
) -> Result<ModuleSpecifier, AnyError> {
if cfg!(windows) {
match ModuleSpecifier::from_file_path(path) {
Ok(url) => Ok(url),
Err(()) => {
let mut url = ModuleSpecifier::parse("file:///").unwrap();
url.set_path(&path.to_string_lossy());
Ok(url)
}
}
} else {
ModuleSpecifier::from_file_path(path).map_err(|()| {
uri_error(format!("Invalid file path.\n Path: {}", path.display()))
})
}
}
/// `from.make_relative(to)` but with fixes. /// `from.make_relative(to)` but with fixes.
pub fn relative_specifier( pub fn relative_specifier(
from: &ModuleSpecifier, from: &ModuleSpecifier,