diff --git a/Cargo.lock b/Cargo.lock index 8decacf1e0..f9c112b620 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1312,9 +1312,9 @@ dependencies = [ [[package]] name = "deno_config" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b72d6f849f5640ed80dc458b529aec74a79bdabdebe291448d345f865faa99" +checksum = "64e7a65603a3aa52216021a0abd401770ac6ed284e5b885dadf40ce35b2a0d9e" dependencies = [ "anyhow", "deno_semver", diff --git a/Cargo.toml b/Cargo.toml index b1e1a20cc3..da1b771591 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ console_static_text = "=0.8.1" data-encoding = "2.3.3" data-url = "=0.3.0" deno_cache_dir = "=0.10.0" -deno_config = { version = "=0.24.0", default-features = false } +deno_config = { version = "=0.25.0", default-features = false } dlopen2 = "0.6.1" ecb = "=0.1.2" elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem"] } diff --git a/cli/args/deno_json.rs b/cli/args/deno_json.rs index 60ac5d58cb..2b3261a0b9 100644 --- a/cli/args/deno_json.rs +++ b/cli/args/deno_json.rs @@ -8,7 +8,7 @@ use deno_semver::jsr::JsrPackageReqReference; use deno_semver::npm::NpmPackageReqReference; pub fn deno_json_deps( - config: &deno_config::ConfigFile, + config: &deno_config::deno_json::ConfigFile, ) -> HashSet { let values = imports_values(config.json.imports.as_ref()) .into_iter() diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 3298d6f83e..8d43846c8b 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -11,7 +11,6 @@ use clap::Command; use clap::ValueHint; use deno_config::glob::FilePatterns; use deno_config::glob::PathOrPatternSet; -use deno_config::ConfigFlag; use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; @@ -42,6 +41,14 @@ use crate::util::fs::canonicalize_path; use super::flags_net; use super::DENO_FUTURE; +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub enum ConfigFlag { + #[default] + Discover, + Path(String), + Disabled, +} + #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct FileFlags { pub ignore: Vec, diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 2c87be0394..c2ea3be4df 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -12,12 +12,12 @@ use deno_config::workspace::CreateResolverOptions; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::VendorEnablement; use deno_config::workspace::Workspace; +use deno_config::workspace::WorkspaceDirectory; +use deno_config::workspace::WorkspaceDirectoryEmptyOptions; use deno_config::workspace::WorkspaceDiscoverOptions; use deno_config::workspace::WorkspaceDiscoverStart; -use deno_config::workspace::WorkspaceEmptyOptions; -use deno_config::workspace::WorkspaceMemberContext; +use deno_config::workspace::WorkspaceLintConfig; use deno_config::workspace::WorkspaceResolver; -use deno_config::WorkspaceLintConfig; use deno_core::normalize_path; use deno_core::resolve_url_or_path; use deno_graph::GraphKind; @@ -32,17 +32,17 @@ use deno_runtime::deno_tls::RootCertStoreProvider; use deno_semver::npm::NpmPackageReqReference; use import_map::resolve_import_map_value_from_specifier; +pub use deno_config::deno_json::BenchConfig; +pub use deno_config::deno_json::ConfigFile; +pub use deno_config::deno_json::FmtOptionsConfig; +pub use deno_config::deno_json::JsxImportSourceConfig; +pub use deno_config::deno_json::LintRulesConfig; +pub use deno_config::deno_json::ProseWrap; +pub use deno_config::deno_json::TsConfig; +pub use deno_config::deno_json::TsConfigForEmit; +pub use deno_config::deno_json::TsConfigType; +pub use deno_config::deno_json::TsTypeLib; pub use deno_config::glob::FilePatterns; -pub use deno_config::BenchConfig; -pub use deno_config::ConfigFile; -pub use deno_config::FmtOptionsConfig; -pub use deno_config::JsxImportSourceConfig; -pub use deno_config::LintRulesConfig; -pub use deno_config::ProseWrap; -pub use deno_config::TsConfig; -pub use deno_config::TsConfigForEmit; -pub use deno_config::TsConfigType; -pub use deno_config::TsTypeLib; pub use flags::*; pub use lockfile::CliLockfile; pub use package_json::PackageJsonInstallDepsProvider; @@ -83,9 +83,9 @@ use crate::file_fetcher::FileFetcher; use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::version; -use deno_config::FmtConfig; -use deno_config::LintConfig; -use deno_config::TestConfig; +use deno_config::deno_json::FmtConfig; +use deno_config::deno_json::LintConfig; +use deno_config::deno_json::TestConfig; pub fn npm_registry_url() -> &'static Url { static NPM_REGISTRY_DEFAULT_URL: Lazy = Lazy::new(|| { @@ -159,9 +159,9 @@ pub fn jsr_api_url() -> &'static Url { } pub fn ts_config_to_transpile_and_emit_options( - config: deno_config::TsConfig, + config: deno_config::deno_json::TsConfig, ) -> Result<(deno_ast::TranspileOptions, deno_ast::EmitOptions), AnyError> { - let options: deno_config::EmitConfigOptions = + let options: deno_config::deno_json::EmitConfigOptions = serde_json::from_value(config.0) .context("Failed to parse compilerOptions")?; let imports_not_used_as_values = @@ -503,7 +503,7 @@ fn resolve_lint_rules_options( pub fn discover_npmrc_from_workspace( workspace: &Workspace, ) -> Result<(Arc, Option), AnyError> { - let root_folder = workspace.root_folder().1; + let root_folder = workspace.root_folder_configs(); discover_npmrc( root_folder.pkg_json.as_ref().map(|p| p.path.clone()), root_folder.deno_json.as_ref().and_then(|cf| { @@ -769,7 +769,7 @@ pub struct CliOptions { npmrc: Arc, maybe_lockfile: Option>, overrides: CliOptionOverrides, - pub workspace: Arc, + pub start_dir: Arc, pub disable_deprecated_api_warning: bool, pub verbose_deprecated_api_warning: bool, } @@ -780,7 +780,7 @@ impl CliOptions { initial_cwd: PathBuf, maybe_lockfile: Option>, npmrc: Arc, - workspace: Arc, + start_dir: Arc, force_global_cache: bool, ) -> Result { if let Some(insecure_allowlist) = @@ -801,7 +801,7 @@ impl CliOptions { } let maybe_lockfile = maybe_lockfile.filter(|_| !force_global_cache); - let root_folder = workspace.root_folder().1; + let root_folder = start_dir.workspace.root_folder_configs(); let maybe_node_modules_folder = resolve_node_modules_folder( &initial_cwd, &flags, @@ -826,7 +826,7 @@ impl CliOptions { npmrc, maybe_node_modules_folder, overrides: Default::default(), - workspace, + start_dir, disable_deprecated_api_warning, verbose_deprecated_api_warning, }) @@ -847,14 +847,13 @@ impl CliOptions { } else { &[] }; - let config_parse_options = deno_config::ConfigParseOptions { + let config_parse_options = deno_config::deno_json::ConfigParseOptions { include_task_comments: matches!( flags.subcommand, DenoSubcommand::Task(..) ), }; - let discover_pkg_json = flags.config_flag - != deno_config::ConfigFlag::Disabled + let discover_pkg_json = flags.config_flag != ConfigFlag::Disabled && !flags.no_npm && !has_flag_env_var("DENO_NO_PACKAGE_JSON"); if !discover_pkg_json { @@ -866,13 +865,14 @@ impl CliOptions { pkg_json_cache: Some( &deno_runtime::deno_node::PackageJsonThreadLocalCache, ), + workspace_cache: None, config_parse_options, additional_config_file_names, discover_pkg_json, maybe_vendor_override, } }; - let resolve_empty_options = || WorkspaceEmptyOptions { + let resolve_empty_options = || WorkspaceDirectoryEmptyOptions { root_dir: Arc::new( ModuleSpecifier::from_directory_path(&initial_cwd).unwrap(), ), @@ -880,36 +880,36 @@ impl CliOptions { .unwrap_or(VendorEnablement::Disable), }; - let workspace = match &flags.config_flag { - deno_config::ConfigFlag::Discover => { + let start_dir = match &flags.config_flag { + ConfigFlag::Discover => { if let Some(start_paths) = flags.config_path_args(&initial_cwd) { - Workspace::discover( + WorkspaceDirectory::discover( WorkspaceDiscoverStart::Paths(&start_paths), &resolve_workspace_discover_options(), )? } else { - Workspace::empty(resolve_empty_options()) + WorkspaceDirectory::empty(resolve_empty_options()) } } - deno_config::ConfigFlag::Path(path) => { + ConfigFlag::Path(path) => { let config_path = normalize_path(initial_cwd.join(path)); - Workspace::discover( + WorkspaceDirectory::discover( WorkspaceDiscoverStart::ConfigFile(&config_path), &resolve_workspace_discover_options(), )? } - deno_config::ConfigFlag::Disabled => { - Workspace::empty(resolve_empty_options()) + ConfigFlag::Disabled => { + WorkspaceDirectory::empty(resolve_empty_options()) } }; - for diagnostic in workspace.diagnostics() { + for diagnostic in start_dir.workspace.diagnostics() { log::warn!("{} {}", colors::yellow("Warning"), diagnostic); } - let (npmrc, _) = discover_npmrc_from_workspace(&workspace)?; + let (npmrc, _) = discover_npmrc_from_workspace(&start_dir.workspace)?; - let maybe_lock_file = CliLockfile::discover(&flags, &workspace)?; + let maybe_lock_file = CliLockfile::discover(&flags, &start_dir.workspace)?; log::debug!("Finished config loading."); @@ -918,7 +918,7 @@ impl CliOptions { initial_cwd, maybe_lock_file.map(Arc::new), npmrc, - Arc::new(workspace), + Arc::new(start_dir), false, ) } @@ -928,6 +928,11 @@ impl CliOptions { &self.initial_cwd } + #[inline(always)] + pub fn workspace(&self) -> &Arc { + &self.start_dir.workspace + } + pub fn graph_kind(&self) -> GraphKind { match self.sub_command() { DenoSubcommand::Cache(_) => GraphKind::All, @@ -1013,7 +1018,7 @@ impl CliOptions { Some(maybe_url) => Ok(maybe_url), None => resolve_import_map_specifier( self.flags.import_map_path.as_deref(), - self.workspace.root_folder().1.deno_json.as_deref(), + self.workspace().root_deno_json().map(|c| c.as_ref()), &self.initial_cwd, ), } @@ -1033,12 +1038,7 @@ impl CliOptions { let cli_arg_specified_import_map = if overrode_no_import_map { // use a fake empty import map Some(deno_config::workspace::SpecifiedImportMap { - base_url: self - .workspace - .root_folder() - .0 - .join("import_map.json") - .unwrap(), + base_url: self.workspace().root_dir().join("import_map.json").unwrap(), value: serde_json::Value::Object(Default::default()), }) } else { @@ -1062,7 +1062,7 @@ impl CliOptions { }; Ok( self - .workspace + .start_dir .create_resolver( CreateResolverOptions { pkg_json_dep_resolution, @@ -1226,7 +1226,7 @@ impl CliOptions { maybe_node_modules_folder: Some(path), npmrc: self.npmrc.clone(), maybe_lockfile: self.maybe_lockfile.clone(), - workspace: self.workspace.clone(), + start_dir: self.start_dir.clone(), overrides: self.overrides.clone(), disable_deprecated_api_warning: self.disable_deprecated_api_warning, verbose_deprecated_api_warning: self.verbose_deprecated_api_warning, @@ -1237,11 +1237,11 @@ impl CliOptions { self .flags .node_modules_dir - .or_else(|| self.workspace.node_modules_dir()) + .or_else(|| self.workspace().node_modules_dir()) } pub fn vendor_dir_path(&self) -> Option<&PathBuf> { - self.workspace.vendor_dir_path() + self.workspace().vendor_dir_path() } pub fn resolve_root_cert_store_provider( @@ -1258,7 +1258,7 @@ impl CliOptions { &self, config_type: TsConfigType, ) -> Result { - let result = self.workspace.resolve_ts_config_for_emit(config_type); + let result = self.workspace().resolve_ts_config_for_emit(config_type); match result { Ok(mut ts_config_for_emit) => { @@ -1301,7 +1301,7 @@ impl CliOptions { &self, ) -> Result, AnyError> { self - .workspace + .workspace() .to_compiler_option_types() .map(|maybe_imports| { maybe_imports @@ -1321,11 +1321,11 @@ impl CliOptions { pub fn resolve_fmt_options_for_members( &self, fmt_flags: &FmtFlags, - ) -> Result, AnyError> { + ) -> Result, AnyError> { let cli_arg_patterns = fmt_flags.files.as_file_patterns(self.initial_cwd())?; let member_configs = self - .workspace + .workspace() .resolve_fmt_config_for_members(&cli_arg_patterns)?; let mut result = Vec::with_capacity(member_configs.len()); for (ctx, config) in member_configs { @@ -1339,18 +1339,18 @@ impl CliOptions { &self, lint_flags: &LintFlags, ) -> Result { - let lint_config = self.workspace.to_lint_config()?; + let lint_config = self.workspace().to_lint_config()?; WorkspaceLintOptions::resolve(&lint_config, lint_flags) } pub fn resolve_lint_options_for_members( &self, lint_flags: &LintFlags, - ) -> Result, AnyError> { + ) -> Result, AnyError> { let cli_arg_patterns = lint_flags.files.as_file_patterns(self.initial_cwd())?; let member_configs = self - .workspace + .workspace() .resolve_lint_config_for_members(&cli_arg_patterns)?; let mut result = Vec::with_capacity(member_configs.len()); for (ctx, config) in member_configs { @@ -1391,16 +1391,16 @@ impl CliOptions { pub fn resolve_test_options_for_members( &self, test_flags: &TestFlags, - ) -> Result, AnyError> { + ) -> Result, AnyError> { let cli_arg_patterns = test_flags.files.as_file_patterns(self.initial_cwd())?; - let member_ctxs = self - .workspace + let workspace_dir_configs = self + .workspace() .resolve_test_config_for_members(&cli_arg_patterns)?; - let mut result = Vec::with_capacity(member_ctxs.len()); - for (member_ctx, config) in member_ctxs { + let mut result = Vec::with_capacity(workspace_dir_configs.len()); + for (member_dir, config) in workspace_dir_configs { let options = TestOptions::resolve(config, test_flags); - result.push((member_ctx, options)); + result.push((member_dir, options)); } Ok(result) } @@ -1415,16 +1415,16 @@ impl CliOptions { pub fn resolve_bench_options_for_members( &self, bench_flags: &BenchFlags, - ) -> Result, AnyError> { + ) -> Result, AnyError> { let cli_arg_patterns = bench_flags.files.as_file_patterns(self.initial_cwd())?; - let member_ctxs = self - .workspace + let workspace_dir_configs = self + .workspace() .resolve_bench_config_for_members(&cli_arg_patterns)?; - let mut result = Vec::with_capacity(member_ctxs.len()); - for (member_ctx, config) in member_ctxs { + let mut result = Vec::with_capacity(workspace_dir_configs.len()); + for (member_dir, config) in workspace_dir_configs { let options = BenchOptions::resolve(config, bench_flags); - result.push((member_ctx, options)); + result.push((member_dir, options)); } Ok(result) } @@ -1433,7 +1433,7 @@ impl CliOptions { &self, ) -> Result, AnyError> { self - .workspace + .workspace() .jsr_packages() .into_iter() .map(|pkg| config_to_deno_graph_workspace_member(&pkg.config_file)) @@ -1454,7 +1454,7 @@ impl CliOptions { } pub fn check_js(&self) -> bool { - self.workspace.check_js() + self.workspace().check_js() } pub fn coverage_dir(&self) -> Option { @@ -1541,7 +1541,7 @@ impl CliOptions { } pub fn no_config(&self) -> bool { - self.flags.config_flag == deno_config::ConfigFlag::Disabled + self.flags.config_flag == ConfigFlag::Disabled } pub fn permission_flags(&self) -> &PermissionFlags { @@ -1601,14 +1601,14 @@ impl CliOptions { pub fn unstable_bare_node_builtins(&self) -> bool { self.flags.unstable_config.bare_node_builtins - || self.workspace.has_unstable("bare-node-builtins") + || self.workspace().has_unstable("bare-node-builtins") } pub fn use_byonm(&self) -> bool { if self.enable_future_features() && self.node_modules_dir_enablement().is_none() && self - .workspace + .workspace() .config_folders() .values() .any(|f| f.pkg_json.is_some()) @@ -1622,16 +1622,16 @@ impl CliOptions { .as_ref() .map(|s| matches!(s.kind, NpmProcessStateKind::Byonm)) .unwrap_or(false) - || self.workspace.has_unstable("byonm") + || self.workspace().has_unstable("byonm") } pub fn unstable_sloppy_imports(&self) -> bool { self.flags.unstable_config.sloppy_imports - || self.workspace.has_unstable("sloppy-imports") + || self.workspace().has_unstable("sloppy-imports") } pub fn unstable_features(&self) -> Vec { - let mut from_config_file = self.workspace.unstable_features().to_vec(); + let mut from_config_file = self.workspace().unstable_features().to_vec(); self .flags @@ -1713,7 +1713,7 @@ impl CliOptions { full_paths.push(import_map_path); } - for (_, folder) in self.workspace.config_folders() { + for (_, folder) in self.workspace().config_folders() { if let Some(deno_json) = &folder.deno_json { if deno_json.specifier.scheme() == "file" { if let Ok(path) = deno_json.specifier.to_file_path() { @@ -1815,8 +1815,7 @@ impl StorageKeyResolver { // otherwise we will use the path to the config file or None to // fall back to using the main module's path options - .workspace - .resolve_start_ctx() + .start_dir .maybe_deno_json() .map(|config_file| Some(config_file.specifier.to_string())) }) @@ -1912,7 +1911,7 @@ mod test { let config_file = ConfigFile::new( config_text, config_specifier, - &deno_config::ConfigParseOptions::default(), + &deno_config::deno_json::ConfigParseOptions::default(), ) .unwrap(); let actual = resolve_import_map_specifier( @@ -1936,7 +1935,7 @@ mod test { let config_file = ConfigFile::new( config_text, config_specifier, - &deno_config::ConfigParseOptions::default(), + &deno_config::deno_json::ConfigParseOptions::default(), ) .unwrap(); let actual = resolve_import_map_specifier( diff --git a/cli/factory.rs b/cli/factory.rs index df7b2c8688..15c36cfd29 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -54,10 +54,10 @@ use crate::worker::CliMainWorkerOptions; use std::collections::BTreeSet; use std::path::PathBuf; +use deno_config::deno_json::ConfigFile; use deno_config::package_json::PackageJsonDepValue; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::WorkspaceResolver; -use deno_config::ConfigFile; use deno_core::error::AnyError; use deno_core::futures::FutureExt; use deno_core::FeatureChecker; @@ -341,7 +341,8 @@ impl CliFactory { // initialize the lockfile with the workspace's configuration if let Some(lockfile) = &maybe_lockfile { - let (root_url, root_folder) = self.options.workspace.root_folder(); + let root_url = self.options.workspace().root_dir(); + let root_folder = self.options.workspace().root_folder_configs(); let config = deno_lockfile::WorkspaceConfig { root: WorkspaceMemberConfig { package_json_deps: pkg_json_deps(root_folder.pkg_json.as_deref()), @@ -349,7 +350,7 @@ impl CliFactory { }, members: self .options - .workspace + .workspace() .config_folders() .iter() .filter(|(folder_url, _)| *folder_url != root_url) @@ -440,7 +441,7 @@ impl CliFactory { text_only_progress_bar: self.text_only_progress_bar().clone(), maybe_node_modules_path: self.options.node_modules_dir_path().cloned(), package_json_deps_provider: Arc::new(PackageJsonInstallDepsProvider::from_workspace( - &self.options.workspace, + self.options.workspace(), )), npm_system_info: self.options.npm_system_info(), npmrc: self.options.npmrc().clone(), @@ -510,7 +511,7 @@ impl CliFactory { .unstable_bare_node_builtins(), maybe_jsx_import_source_config: self .options - .workspace + .workspace() .to_maybe_jsx_import_source_config()?, maybe_vendor_dir: self.options.vendor_dir_path(), }))) diff --git a/cli/graph_container.rs b/cli/graph_container.rs index d439f93609..cf913464fd 100644 --- a/cli/graph_container.rs +++ b/cli/graph_container.rs @@ -98,7 +98,7 @@ impl MainModuleGraphContainer { &self, files: &[String], ) -> Result, AnyError> { - let excludes = self.cli_options.workspace.resolve_config_excludes()?; + let excludes = self.cli_options.workspace().resolve_config_excludes()?; Ok( files .iter() diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index 5b549fc39b..2757500d1a 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -1,6 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_ast::MediaType; +use deno_config::deno_json::DenoJsonCache; +use deno_config::deno_json::FmtConfig; +use deno_config::deno_json::FmtOptionsConfig; +use deno_config::deno_json::LintConfig; +use deno_config::deno_json::TestConfig; +use deno_config::deno_json::TsConfig; use deno_config::fs::DenoConfigFs; use deno_config::fs::RealDenoConfigFs; use deno_config::glob::FilePatterns; @@ -11,14 +17,11 @@ use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::SpecifiedImportMap; use deno_config::workspace::VendorEnablement; use deno_config::workspace::Workspace; +use deno_config::workspace::WorkspaceCache; +use deno_config::workspace::WorkspaceDirectory; +use deno_config::workspace::WorkspaceDirectoryEmptyOptions; use deno_config::workspace::WorkspaceDiscoverOptions; -use deno_config::workspace::WorkspaceEmptyOptions; -use deno_config::workspace::WorkspaceMemberContext; use deno_config::workspace::WorkspaceResolver; -use deno_config::DenoJsonCache; -use deno_config::FmtConfig; -use deno_config::FmtOptionsConfig; -use deno_config::TsConfig; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; @@ -29,6 +32,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; +use deno_lint::linter::LintConfig as DenoLintConfig; use deno_npm::npm_rc::ResolvedNpmRc; use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_permissions::PermissionsContainer; @@ -1107,13 +1111,12 @@ pub enum ConfigWatchedFileType { #[derive(Debug, Clone)] pub struct ConfigData { pub scope: Arc, - pub workspace: Arc, - pub member_ctx: Arc, - pub fmt_config: Arc, - pub lint_config: Arc, - pub test_config: Arc, + pub member_dir: Arc, + pub fmt_config: Arc, + pub lint_config: Arc, + pub test_config: Arc, pub exclude_files: Arc, - pub deno_lint_config: deno_lint::linter::LintConfig, + pub deno_lint_config: DenoLintConfig, pub lint_rules: Arc, pub ts_config: Arc, pub byonm: bool, @@ -1127,6 +1130,7 @@ pub struct ConfigData { } impl ConfigData { + #[allow(clippy::too_many_arguments)] async fn load( specified_config: Option<&Path>, scope: &ModuleSpecifier, @@ -1136,12 +1140,13 @@ impl ConfigData { cached_deno_config_fs: &(dyn DenoConfigFs + Sync), deno_json_cache: &(dyn DenoJsonCache + Sync), pkg_json_cache: &(dyn PackageJsonCache + Sync), + workspace_cache: &(dyn WorkspaceCache + Sync), ) -> Self { let scope = Arc::new(scope.clone()); let discover_result = match scope.to_file_path() { Ok(scope_dir_path) => { let paths = [scope_dir_path]; - Workspace::discover( + WorkspaceDirectory::discover( match specified_config { Some(config_path) => { deno_config::workspace::WorkspaceDiscoverStart::ConfigFile( @@ -1157,6 +1162,7 @@ impl ConfigData { additional_config_file_names: &[], deno_json_cache: Some(deno_json_cache), pkg_json_cache: Some(pkg_json_cache), + workspace_cache: Some(workspace_cache), discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"), config_parse_options: Default::default(), maybe_vendor_override: None, @@ -1168,17 +1174,18 @@ impl ConfigData { Err(()) => Err(anyhow!("Scope '{}' was not a directory path.", scope)), }; match discover_result { - Ok(workspace) => { - Self::load_inner(workspace, scope, settings, Some(file_fetcher)).await + Ok(member_dir) => { + Self::load_inner(member_dir, scope, settings, Some(file_fetcher)).await } Err(err) => { lsp_warn!(" Couldn't open workspace \"{}\": {}", scope.as_str(), err); - let workspace = Arc::new(Workspace::empty(WorkspaceEmptyOptions { - root_dir: scope.clone(), - use_vendor_dir: VendorEnablement::Disable, - })); + let member_dir = + Arc::new(WorkspaceDirectory::empty(WorkspaceDirectoryEmptyOptions { + root_dir: scope.clone(), + use_vendor_dir: VendorEnablement::Disable, + })); let mut data = Self::load_inner( - workspace, + member_dir, scope.clone(), settings, Some(file_fetcher), @@ -1220,7 +1227,7 @@ impl ConfigData { } async fn load_inner( - workspace: Arc, + member_dir: Arc, scope: Arc, settings: &Settings, file_fetcher: Option<&Arc>, @@ -1242,9 +1249,7 @@ impl ConfigData { watched_files.entry(specifier).or_insert(file_type); }; - let member_ctx = workspace.resolve_start_ctx(); - - if let Some(deno_json) = member_ctx.maybe_deno_json() { + if let Some(deno_json) = member_dir.maybe_deno_json() { lsp_log!( " Resolved Deno configuration file: \"{}\"", deno_json.specifier @@ -1256,7 +1261,7 @@ impl ConfigData { ); } - if let Some(pkg_json) = member_ctx.maybe_pkg_json() { + if let Some(pkg_json) = member_dir.maybe_pkg_json() { lsp_log!(" Resolved package.json: \"{}\"", pkg_json.specifier()); add_watched_file( @@ -1266,7 +1271,7 @@ impl ConfigData { } // todo(dsherret): cache this so we don't load this so many times - let npmrc = discover_npmrc_from_workspace(&workspace) + let npmrc = discover_npmrc_from_workspace(&member_dir.workspace) .inspect(|(_, path)| { if let Some(path) = path { lsp_log!(" Resolved .npmrc: \"{}\"", path.display()); @@ -1281,51 +1286,48 @@ impl ConfigData { }) .map(|(r, _)| r) .ok(); - let default_file_patterns = scope - .to_file_path() - .map(FilePatterns::new_with_base) - .unwrap_or_else(|_| FilePatterns::new_with_base(PathBuf::from("/"))); + let default_file_pattern_base = + scope.to_file_path().unwrap_or_else(|_| PathBuf::from("/")); let fmt_config = Arc::new( - member_ctx - .to_fmt_config(FilePatterns::new_with_base(member_ctx.dir_path())) + member_dir + .to_fmt_config(FilePatterns::new_with_base(member_dir.dir_path())) .inspect_err(|err| { lsp_warn!(" Couldn't read formatter configuration: {}", err) }) .ok() - .unwrap_or_else(|| deno_config::FmtConfig { - options: Default::default(), - files: default_file_patterns.clone(), + .unwrap_or_else(|| { + FmtConfig::new_with_base(default_file_pattern_base.clone()) }), ); let lint_config = Arc::new( - member_ctx - .to_lint_config(FilePatterns::new_with_base(member_ctx.dir_path())) + member_dir + .to_lint_config(FilePatterns::new_with_base(member_dir.dir_path())) .inspect_err(|err| { lsp_warn!(" Couldn't read lint configuration: {}", err) }) .ok() - .unwrap_or_else(|| deno_config::LintConfig { - options: Default::default(), - files: default_file_patterns.clone(), + .unwrap_or_else(|| { + LintConfig::new_with_base(default_file_pattern_base.clone()) }), ); let lint_rules = Arc::new(get_configured_rules( lint_config.options.rules.clone(), - member_ctx.maybe_deno_json().map(|c| c.as_ref()), + member_dir.maybe_deno_json().map(|c| c.as_ref()), )); let test_config = Arc::new( - member_ctx - .to_test_config(FilePatterns::new_with_base(member_ctx.dir_path())) + member_dir + .to_test_config(FilePatterns::new_with_base(member_dir.dir_path())) .inspect_err(|err| { lsp_warn!(" Couldn't read test configuration: {}", err) }) .ok() - .unwrap_or_else(|| deno_config::TestConfig { - files: default_file_patterns.clone(), + .unwrap_or_else(|| { + TestConfig::new_with_base(default_file_pattern_base.clone()) }), ); let exclude_files = Arc::new( - workspace + member_dir + .workspace .resolve_config_excludes() .inspect_err(|err| { lsp_warn!(" Couldn't read config excludes: {}", err) @@ -1334,8 +1336,9 @@ impl ConfigData { .unwrap_or_default(), ); - let ts_config = - LspTsConfig::new(workspace.root_deno_json().map(|c| c.as_ref())); + let ts_config = LspTsConfig::new( + member_dir.workspace.root_deno_json().map(|c| c.as_ref()), + ); let deno_lint_config = if ts_config.inner.0.get("jsx").and_then(|v| v.as_str()) == Some("react") @@ -1347,21 +1350,21 @@ impl ConfigData { .0 .get("jsxFragmentFactory") .and_then(|v| v.as_str()); - deno_lint::linter::LintConfig { + DenoLintConfig { default_jsx_factory: default_jsx_factory.map(String::from), default_jsx_fragment_factory: default_jsx_fragment_factory .map(String::from), } } else { - deno_lint::linter::LintConfig { + DenoLintConfig { default_jsx_factory: None, default_jsx_fragment_factory: None, } }; - let vendor_dir = workspace.vendor_dir_path().cloned(); + let vendor_dir = member_dir.workspace.vendor_dir_path().cloned(); // todo(dsherret): add caching so we don't load this so many times - let lockfile = resolve_lockfile_from_workspace(&workspace).map(Arc::new); + let lockfile = resolve_lockfile_from_workspace(&member_dir).map(Arc::new); if let Some(lockfile) = &lockfile { if let Ok(specifier) = ModuleSpecifier::from_file_path(&lockfile.filename) { @@ -1370,18 +1373,22 @@ impl ConfigData { } let byonm = std::env::var("DENO_UNSTABLE_BYONM").is_ok() - || workspace.has_unstable("byonm") + || member_dir.workspace.has_unstable("byonm") || (*DENO_FUTURE - && workspace.package_jsons().next().is_some() - && workspace.node_modules_dir().is_none()); + && member_dir.workspace.package_jsons().next().is_some() + && member_dir.workspace.node_modules_dir().is_none()); if byonm { lsp_log!(" Enabled 'bring your own node_modules'."); } - let node_modules_dir = resolve_node_modules_dir(&workspace, byonm); + let node_modules_dir = + resolve_node_modules_dir(&member_dir.workspace, byonm); // Mark the import map as a watched file - if let Some(import_map_specifier) = - workspace.to_import_map_specifier().ok().flatten() + if let Some(import_map_specifier) = member_dir + .workspace + .to_import_map_specifier() + .ok() + .flatten() { add_watched_file( import_map_specifier.clone(), @@ -1396,11 +1403,12 @@ impl ConfigData { PackageJsonDepResolution::Enabled }; let mut import_map_from_settings = { - let is_config_import_map = member_ctx + let is_config_import_map = member_dir .maybe_deno_json() .map(|c| c.is_an_import_map() || c.json.import_map.is_some()) .or_else(|| { - workspace + member_dir + .workspace .root_deno_json() .map(|c| c.is_an_import_map() || c.json.import_map.is_some()) }) @@ -1417,11 +1425,12 @@ impl ConfigData { }; let specified_import_map = { - let is_config_import_map = member_ctx + let is_config_import_map = member_dir .maybe_deno_json() .map(|c| c.is_an_import_map() || c.json.import_map.is_some()) .or_else(|| { - workspace + member_dir + .workspace .root_deno_json() .map(|c| c.is_an_import_map() || c.json.import_map.is_some()) }) @@ -1470,7 +1479,7 @@ impl ConfigData { } }; let resolver = deno_core::unsync::spawn({ - let workspace = workspace.clone(); + let workspace = member_dir.clone(); let file_fetcher = file_fetcher.cloned(); async move { workspace @@ -1508,7 +1517,7 @@ impl ConfigData { WorkspaceResolver::new_raw( scope.clone(), None, - workspace.package_jsons().cloned().collect(), + member_dir.workspace.package_jsons().cloned().collect(), pkg_json_dep_resolution, ) }); @@ -1526,8 +1535,7 @@ impl ConfigData { ConfigData { scope, - workspace, - member_ctx: Arc::new(member_ctx), + member_dir, resolver: Arc::new(resolver), fmt_config, lint_config, @@ -1546,14 +1554,16 @@ impl ConfigData { } } - pub fn maybe_deno_json(&self) -> Option<&Arc> { - self.member_ctx.maybe_deno_json() + pub fn maybe_deno_json( + &self, + ) -> Option<&Arc> { + self.member_dir.maybe_deno_json() } pub fn maybe_pkg_json( &self, ) -> Option<&Arc> { - self.member_ctx.maybe_pkg_json() + self.member_dir.maybe_pkg_json() } } @@ -1588,11 +1598,13 @@ impl ConfigTree { &self.scopes } - pub fn workspace_member_ctx_for_specifier( + pub fn workspace_dir_for_specifier( &self, specifier: &ModuleSpecifier, - ) -> Option<&Arc> { - self.data_for_specifier(specifier).map(|d| &d.member_ctx) + ) -> Option<&WorkspaceDirectory> { + self + .data_for_specifier(specifier) + .map(|d| d.member_dir.as_ref()) } pub fn config_files(&self) -> Vec<&Arc> { @@ -1618,12 +1630,7 @@ impl ConfigTree { self .data_for_specifier(specifier) .map(|d| d.fmt_config.clone()) - .unwrap_or_else(|| { - Arc::new(FmtConfig { - options: Default::default(), - files: FilePatterns::new_with_base(PathBuf::from("/")), - }) - }) + .unwrap_or_else(|| Arc::new(FmtConfig::new_with_base(PathBuf::from("/")))) } /// Returns (scope_uri, type). @@ -1665,6 +1672,7 @@ impl ConfigTree { let cached_fs = CachedDenoConfigFs::default(); let deno_json_cache = DenoJsonMemCache::default(); let pkg_json_cache = PackageJsonMemCache::default(); + let workspace_cache = WorkspaceMemCache::default(); let mut scopes = BTreeMap::new(); for (folder_uri, ws_settings) in &settings.by_workspace_folder { let mut ws_settings = ws_settings.as_ref(); @@ -1686,6 +1694,7 @@ impl ConfigTree { &cached_fs, &deno_json_cache, &pkg_json_cache, + &workspace_cache, ) .await, ), @@ -1718,11 +1727,12 @@ impl ConfigTree { &cached_fs, &deno_json_cache, &pkg_json_cache, + &workspace_cache, ) .await, ); scopes.insert(scope, data.clone()); - for (member_scope, _) in data.workspace.config_folders() { + for (member_scope, _) in data.member_dir.workspace.config_folders() { if scopes.contains_key(member_scope) { continue; } @@ -1734,6 +1744,7 @@ impl ConfigTree { &cached_fs, &deno_json_cache, &pkg_json_cache, + &workspace_cache, ) .await; scopes.insert(member_scope.as_ref().clone(), Arc::new(member_data)); @@ -1756,6 +1767,7 @@ impl ConfigTree { &cached_fs, &deno_json_cache, &pkg_json_cache, + &workspace_cache, ) .await, ), @@ -1775,8 +1787,8 @@ impl ConfigTree { config_path.to_string_lossy().to_string(), json_text, )]); - let workspace = Arc::new( - Workspace::discover( + let workspace_dir = Arc::new( + WorkspaceDirectory::discover( deno_config::workspace::WorkspaceDiscoverStart::ConfigFile( &config_path, ), @@ -1789,7 +1801,7 @@ impl ConfigTree { ); let data = Arc::new( ConfigData::load_inner( - workspace, + workspace_dir, Arc::new(scope.clone()), &Default::default(), None, @@ -1802,9 +1814,9 @@ impl ConfigTree { } fn resolve_lockfile_from_workspace( - workspace: &Workspace, + workspace: &WorkspaceDirectory, ) -> Option { - let lockfile_path = match workspace.resolve_lockfile_path() { + let lockfile_path = match workspace.workspace.resolve_lockfile_path() { Ok(Some(value)) => value, Ok(None) => return None, Err(err) => { @@ -1834,8 +1846,7 @@ fn resolve_node_modules_dir( return None; } let node_modules_dir = workspace - .root_folder() - .0 + .root_dir() .to_file_path() .ok()? .join("node_modules"); @@ -1864,7 +1875,7 @@ fn resolve_lockfile_from_path(lockfile_path: PathBuf) -> Option { #[derive(Default)] struct DenoJsonMemCache(Mutex>>); -impl deno_config::DenoJsonCache for DenoJsonMemCache { +impl deno_config::deno_json::DenoJsonCache for DenoJsonMemCache { fn get(&self, path: &Path) -> Option> { self.0.lock().get(path).cloned() } @@ -1887,6 +1898,19 @@ impl deno_config::package_json::PackageJsonCache for PackageJsonMemCache { } } +#[derive(Default)] +struct WorkspaceMemCache(Mutex>>); + +impl deno_config::workspace::WorkspaceCache for WorkspaceMemCache { + fn get(&self, dir_path: &Path) -> Option> { + self.0.lock().get(dir_path).cloned() + } + + fn set(&self, dir_path: PathBuf, workspace: Arc) { + self.0.lock().insert(dir_path, workspace); + } +} + #[derive(Default)] struct CachedFsItems { items: HashMap>, @@ -1920,7 +1944,6 @@ impl CachedFsItems { struct InnerData { stat_calls: CachedFsItems, read_to_string_calls: CachedFsItems, - read_dir_calls: CachedFsItems>, } #[derive(Default)] @@ -1953,22 +1976,23 @@ impl DenoConfigFs for CachedDenoConfigFs { &self, path: &Path, ) -> Result, std::io::Error> { - self - .0 - .lock() - .read_dir_calls - .get(path, |path| RealDenoConfigFs.read_dir(path)) + // no need to cache these because the workspace cache will ensure + // we only do read_dir calls once (read_dirs are only used for + // npm workspace resolution) + RealDenoConfigFs.read_dir(path) } } #[cfg(test)] mod tests { - use super::*; + use deno_config::deno_json::ConfigParseOptions; use deno_core::resolve_url; use deno_core::serde_json; use deno_core::serde_json::json; use pretty_assertions::assert_eq; + use super::*; + #[test] fn test_config_specifier_enabled() { let root_uri = resolve_url("file:///").unwrap(); @@ -2234,7 +2258,7 @@ mod tests { ConfigFile::new( "{}", root_uri.join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) @@ -2292,7 +2316,7 @@ mod tests { }) .to_string(), root_uri.join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) @@ -2318,7 +2342,7 @@ mod tests { }) .to_string(), root_uri.join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) @@ -2336,7 +2360,7 @@ mod tests { }) .to_string(), root_uri.join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 02d51a2eb9..53a6fd7d31 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -23,7 +23,7 @@ use crate::resolver::SloppyImportsResolver; use crate::util::path::to_percent_decoded_str; use deno_ast::MediaType; -use deno_config::glob::FilePatterns; +use deno_config::deno_json::LintConfig; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::parking_lot::RwLock; @@ -39,6 +39,7 @@ use deno_graph::source::ResolutionMode; use deno_graph::Resolution; use deno_graph::ResolutionError; use deno_graph::SpecifierError; +use deno_lint::linter::LintConfig as DenoLintConfig; use deno_lint::rules::LintRule; use deno_runtime::deno_fs; use deno_runtime::deno_node; @@ -827,11 +828,8 @@ fn generate_lint_diagnostics( }) .unwrap_or_else(|| { ( - Arc::new(deno_config::LintConfig { - options: Default::default(), - files: FilePatterns::new_with_base(PathBuf::from("/")), - }), - deno_lint::linter::LintConfig { + Arc::new(LintConfig::new_with_base(PathBuf::from("/"))), + DenoLintConfig { default_jsx_factory: None, default_jsx_fragment_factory: None, }, @@ -856,8 +854,8 @@ fn generate_lint_diagnostics( fn generate_document_lint_diagnostics( document: &Document, - lint_config: &deno_config::LintConfig, - deno_lint_config: deno_lint::linter::LintConfig, + lint_config: &LintConfig, + deno_lint_config: DenoLintConfig, lint_rules: Vec<&'static dyn LintRule>, ) -> Vec { if !lint_config.files.matches_specifier(document.specifier()) { @@ -1611,7 +1609,6 @@ fn generate_deno_diagnostics( #[cfg(test)] mod tests { - use super::*; use crate::lsp::cache::LspCache; use crate::lsp::config::Config; @@ -1621,7 +1618,8 @@ mod tests { use crate::lsp::documents::LanguageId; use crate::lsp::language_server::StateSnapshot; use crate::lsp::resolver::LspResolver; - use deno_config::ConfigFile; + + use deno_config::deno_json::ConfigFile; use pretty_assertions::assert_eq; use std::sync::Arc; use test_util::TempDir; @@ -1661,7 +1659,7 @@ mod tests { let config_file = ConfigFile::new( json_string, base_url, - &deno_config::ConfigParseOptions::default(), + &deno_config::deno_json::ConfigParseOptions::default(), ) .unwrap(); config.tree.inject_config_file(config_file).await; diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 48cfebfcc4..811587a8dd 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -1597,7 +1597,9 @@ fn analyze_module( mod tests { use super::*; use crate::lsp::cache::LspCache; - use deno_config::ConfigFile; + + use deno_config::deno_json::ConfigFile; + use deno_config::deno_json::ConfigParseOptions; use deno_core::serde_json; use deno_core::serde_json::json; use pretty_assertions::assert_eq; @@ -1751,7 +1753,7 @@ console.log(b, "hello deno"); }) .to_string(), config.root_uri().unwrap().join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) @@ -1795,7 +1797,7 @@ console.log(b, "hello deno"); }) .to_string(), config.root_uri().unwrap().join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &ConfigParseOptions::default(), ) .unwrap(), ) diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index 05eb76599a..b02e01fb6d 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -49,7 +49,7 @@ impl JsrCacheResolver { let info_by_name = DashMap::new(); let mut workspace_scope_by_name = HashMap::new(); if let Some(config_data) = config_data { - for jsr_pkg_config in config_data.workspace.jsr_packages() { + for jsr_pkg_config in config_data.member_dir.workspace.jsr_packages() { let Some(exports) = &jsr_pkg_config.config_file.json.exports else { continue; }; diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 5b6ff79f21..7db1553096 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -2,7 +2,7 @@ use base64::Engine; use deno_ast::MediaType; -use deno_config::workspace::Workspace; +use deno_config::workspace::WorkspaceDirectory; use deno_config::workspace::WorkspaceDiscoverOptions; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; @@ -3556,27 +3556,30 @@ impl Inner { let initial_cwd = config_data .and_then(|d| d.scope.to_file_path().ok()) .unwrap_or_else(|| self.initial_cwd.clone()); - // todo: we need a way to convert config data to a Workspace - let workspace = Arc::new(Workspace::discover( - deno_config::workspace::WorkspaceDiscoverStart::Paths(&[ - initial_cwd.clone() - ]), - &WorkspaceDiscoverOptions { - fs: &DenoConfigFsAdapter::new(&deno_runtime::deno_fs::RealFs), - deno_json_cache: None, - pkg_json_cache: None, - config_parse_options: deno_config::ConfigParseOptions { - include_task_comments: false, + let workspace = match config_data { + Some(d) => d.member_dir.clone(), + None => Arc::new(WorkspaceDirectory::discover( + deno_config::workspace::WorkspaceDiscoverStart::Paths(&[ + initial_cwd.clone() + ]), + &WorkspaceDiscoverOptions { + fs: &DenoConfigFsAdapter::new(&deno_runtime::deno_fs::RealFs), + deno_json_cache: None, + pkg_json_cache: None, + workspace_cache: None, + config_parse_options: deno_config::deno_json::ConfigParseOptions { + include_task_comments: false, + }, + additional_config_file_names: &[], + discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"), + maybe_vendor_override: if force_global_cache { + Some(deno_config::workspace::VendorEnablement::Disable) + } else { + None + }, }, - additional_config_file_names: &[], - discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"), - maybe_vendor_override: if force_global_cache { - Some(deno_config::workspace::VendorEnablement::Disable) - } else { - None - }, - }, - )?); + )?), + }; let cli_options = CliOptions::new( Flags { cache_path: Some(self.cache.deno_dir().root.clone()), diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 2f03842b12..7758bbd7cd 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -115,7 +115,7 @@ impl LspScopeResolver { ))); let npm_graph_resolver = graph_resolver.create_graph_npm_resolver(); let graph_imports = config_data - .and_then(|d| d.workspace.to_compiler_option_types().ok()) + .and_then(|d| d.member_dir.workspace.to_compiler_option_types().ok()) .map(|imports| { Arc::new( imports @@ -513,9 +513,9 @@ fn create_graph_resolver( npm_resolver: Option<&Arc>, node_resolver: Option<&Arc>, ) -> Arc { - let workspace = config_data.map(|d| &d.workspace); + let workspace = config_data.map(|d| &d.member_dir.workspace); let unstable_sloppy_imports = - workspace.is_some_and(|w| w.has_unstable("sloppy-imports")); + workspace.is_some_and(|dir| dir.has_unstable("sloppy-imports")); Arc::new(CliGraphResolver::new(CliGraphResolverOptions { node_resolver: node_resolver.cloned(), npm_resolver: npm_resolver.cloned(), @@ -530,11 +530,12 @@ fn create_graph_resolver( )) }, ), - maybe_jsx_import_source_config: workspace - .and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten()), + maybe_jsx_import_source_config: workspace.and_then(|workspace| { + workspace.to_maybe_jsx_import_source_config().ok().flatten() + }), maybe_vendor_dir: config_data.and_then(|d| d.vendor_dir.as_ref()), bare_node_builtins_enabled: workspace - .is_some_and(|cf| cf.has_unstable("bare-node-builtins")), + .is_some_and(|workspace| workspace.has_unstable("bare-node-builtins")), sloppy_imports_resolver: unstable_sloppy_imports.then(|| { SloppyImportsResolver::new_without_stat_cache(Arc::new(deno_fs::RealFs)) }), diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 9dabb6ca51..6c808a5e40 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -5012,7 +5012,7 @@ impl UserPreferences { // Only use workspace settings for quote style if there's no `deno.json`. quote_preference: if config .tree - .workspace_member_ctx_for_specifier(specifier) + .workspace_dir_for_specifier(specifier) .is_some_and(|ctx| ctx.maybe_deno_json().is_some()) { base_preferences.quote_preference @@ -5407,13 +5407,13 @@ mod tests { config .tree .inject_config_file( - deno_config::ConfigFile::new( + deno_config::deno_json::ConfigFile::new( &json!({ "compilerOptions": ts_config, }) .to_string(), temp_dir.uri().join("deno.json").unwrap(), - &deno_config::ConfigParseOptions::default(), + &Default::default(), ) .unwrap(), ) diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index 342c637d54..85d131f42c 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -733,18 +733,13 @@ impl<'a> DenoCompileBinaryWriter<'a> { InnerCliNpmResolverRef::Byonm(_) => { maybe_warn_different_system(&self.npm_system_info); let mut builder = VfsBuilder::new(root_path.to_path_buf())?; - for pkg_json in cli_options.workspace.package_jsons() { + for pkg_json in cli_options.workspace().package_jsons() { builder.add_file_at_path(&pkg_json.path)?; } // traverse and add all the node_modules directories in the workspace let mut pending_dirs = VecDeque::new(); pending_dirs.push_back( - cli_options - .workspace - .root_folder() - .0 - .to_file_path() - .unwrap(), + cli_options.workspace().root_dir().to_file_path().unwrap(), ); while let Some(pending_dir) = pending_dirs.pop_front() { let entries = fs::read_dir(&pending_dir).with_context(|| { diff --git a/cli/tools/compile.rs b/cli/tools/compile.rs index e395c351b7..5500f9512d 100644 --- a/cli/tools/compile.rs +++ b/cli/tools/compile.rs @@ -77,15 +77,15 @@ pub async fn compile( graph }; - let ts_config_for_emit = - cli_options.resolve_ts_config_for_emit(deno_config::TsConfigType::Emit)?; + let ts_config_for_emit = cli_options + .resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?; let (transpile_options, emit_options) = crate::args::ts_config_to_transpile_and_emit_options( ts_config_for_emit.ts_config, )?; let parser = parsed_source_cache.as_capturing_parser(); let root_dir_url = resolve_root_dir_from_specifiers( - cli_options.workspace.root_folder().0, + cli_options.workspace().root_dir(), graph.specifiers().map(|(s, _)| s).chain( cli_options .node_modules_dir_path() diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index 79765a91d4..138e0a47d1 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -187,32 +187,31 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> { Default::default() }; - let rewrite_map = if let Some(config_file) = - cli_options.workspace.resolve_start_ctx().maybe_deno_json() - { - let config = config_file.to_exports_config()?; + let rewrite_map = + if let Some(config_file) = cli_options.start_dir.maybe_deno_json() { + let config = config_file.to_exports_config()?; - let rewrite_map = config - .clone() - .into_map() - .into_keys() - .map(|key| { - Ok(( - config.get_resolved(&key)?.unwrap(), - key - .strip_prefix('.') - .unwrap_or(&key) - .strip_prefix('/') - .unwrap_or(&key) - .to_owned(), - )) - }) - .collect::, AnyError>>()?; + let rewrite_map = config + .clone() + .into_map() + .into_keys() + .map(|key| { + Ok(( + config.get_resolved(&key)?.unwrap(), + key + .strip_prefix('.') + .unwrap_or(&key) + .strip_prefix('/') + .unwrap_or(&key) + .to_owned(), + )) + }) + .collect::, AnyError>>()?; - Some(rewrite_map) - } else { - None - }; + Some(rewrite_map) + } else { + None + }; generate_docs_directory( doc_nodes_by_url, diff --git a/cli/tools/fmt.rs b/cli/tools/fmt.rs index 040991e7c2..277a79cda0 100644 --- a/cli/tools/fmt.rs +++ b/cli/tools/fmt.rs @@ -52,9 +52,9 @@ use crate::cache::IncrementalCache; pub async fn format(flags: Flags, fmt_flags: FmtFlags) -> Result<(), AnyError> { if fmt_flags.is_stdin() { let cli_options = CliOptions::from_flags(flags)?; - let start_ctx = cli_options.workspace.resolve_start_ctx(); - let fmt_config = start_ctx - .to_fmt_config(FilePatterns::new_with_base(start_ctx.dir_path()))?; + let start_dir = &cli_options.start_dir; + let fmt_config = start_dir + .to_fmt_config(FilePatterns::new_with_base(start_dir.dir_path()))?; let fmt_options = FmtOptions::resolve(fmt_config, &fmt_flags); return format_stdin( &fmt_flags, diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs index 9d5b6baf37..b7b9b4d96c 100644 --- a/cli/tools/installer.rs +++ b/cli/tools/installer.rs @@ -3,6 +3,7 @@ use crate::args::resolve_no_prompt; use crate::args::AddFlags; use crate::args::CaData; +use crate::args::ConfigFlag; use crate::args::Flags; use crate::args::InstallFlags; use crate::args::InstallFlagsGlobal; @@ -14,7 +15,6 @@ use crate::factory::CliFactory; use crate::http_util::HttpClientProvider; use crate::util::fs::canonicalize_path_maybe_not_exists; -use deno_config::ConfigFlag; use deno_core::anyhow::Context; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -571,11 +571,11 @@ fn is_in_path(dir: &Path) -> bool { mod tests { use super::*; + use crate::args::ConfigFlag; use crate::args::PermissionFlags; use crate::args::UninstallFlagsGlobal; use crate::args::UnstableConfig; use crate::util::fs::canonicalize_path; - use deno_config::ConfigFlag; use std::process::Command; use test_util::testdata_path; use test_util::TempDir; diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index 2754262657..05458a7b0d 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -8,10 +8,10 @@ use deno_ast::ModuleSpecifier; use deno_ast::ParsedSource; use deno_ast::SourceRange; use deno_ast::SourceTextInfo; +use deno_config::deno_json::ConfigFile; use deno_config::glob::FileCollector; use deno_config::glob::FilePatterns; -use deno_config::workspace::Workspace; -use deno_config::workspace::WorkspaceMemberContext; +use deno_config::workspace::WorkspaceDirectory; use deno_core::anyhow::anyhow; use deno_core::anyhow::bail; use deno_core::anyhow::Context; @@ -118,7 +118,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { let mut linter = WorkspaceLinter::new( factory.caches()?.clone(), factory.module_graph_creator().await?.clone(), - cli_options.workspace.clone(), + cli_options.start_dir.clone(), &cli_options.resolve_workspace_lint_options(&lint_flags)?, ); for paths_with_options in paths_with_options_batches { @@ -126,7 +126,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { .lint_files( paths_with_options.options, lint_config.clone(), - paths_with_options.ctx, + paths_with_options.dir, paths_with_options.paths, ) .await?; @@ -147,16 +147,16 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { let workspace_lint_options = cli_options.resolve_workspace_lint_options(&lint_flags)?; let success = if is_stdin { - let start_ctx = cli_options.workspace.resolve_start_ctx(); + let start_dir = &cli_options.start_dir; let reporter_lock = Arc::new(Mutex::new(create_reporter( workspace_lint_options.reporter_kind, ))); - let lint_config = start_ctx - .to_lint_config(FilePatterns::new_with_base(start_ctx.dir_path()))?; + let lint_config = start_dir + .to_lint_config(FilePatterns::new_with_base(start_dir.dir_path()))?; let lint_options = LintOptions::resolve(lint_config, &lint_flags); let lint_rules = get_config_rules_err_empty( lint_options.rules, - start_ctx.maybe_deno_json().map(|c| c.as_ref()), + start_dir.maybe_deno_json().map(|c| c.as_ref()), )?; let file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME); let r = lint_stdin(&file_path, lint_rules.rules, deno_lint_config); @@ -171,7 +171,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { let mut linter = WorkspaceLinter::new( factory.caches()?.clone(), factory.module_graph_creator().await?.clone(), - cli_options.workspace.clone(), + cli_options.start_dir.clone(), &workspace_lint_options, ); let paths_with_options_batches = @@ -181,7 +181,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { .lint_files( paths_with_options.options, deno_lint_config.clone(), - paths_with_options.ctx, + paths_with_options.dir, paths_with_options.paths, ) .await?; @@ -197,7 +197,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> { } struct PathsWithOptions { - ctx: WorkspaceMemberContext, + dir: WorkspaceDirectory, paths: Vec, options: LintOptions, } @@ -210,11 +210,11 @@ fn resolve_paths_with_options_batches( cli_options.resolve_lint_options_for_members(lint_flags)?; let mut paths_with_options_batches = Vec::with_capacity(members_lint_options.len()); - for (ctx, lint_options) in members_lint_options { + for (dir, lint_options) in members_lint_options { let files = collect_lint_files(cli_options, lint_options.files.clone())?; if !files.is_empty() { paths_with_options_batches.push(PathsWithOptions { - ctx, + dir, paths: files, options: lint_options, }); @@ -232,7 +232,7 @@ type WorkspaceModuleGraphFuture = struct WorkspaceLinter { caches: Arc, module_graph_creator: Arc, - workspace: Arc, + workspace_dir: Arc, reporter_lock: Arc>>, workspace_module_graph: Option, has_error: Arc, @@ -243,7 +243,7 @@ impl WorkspaceLinter { pub fn new( caches: Arc, module_graph_creator: Arc, - workspace: Arc, + workspace_dir: Arc, workspace_options: &WorkspaceLintOptions, ) -> Self { let reporter_lock = @@ -251,7 +251,7 @@ impl WorkspaceLinter { Self { caches, module_graph_creator, - workspace, + workspace_dir, reporter_lock, workspace_module_graph: None, has_error: Default::default(), @@ -263,14 +263,14 @@ impl WorkspaceLinter { &mut self, lint_options: LintOptions, lint_config: LintConfig, - member_ctx: WorkspaceMemberContext, + member_dir: WorkspaceDirectory, paths: Vec, ) -> Result<(), AnyError> { self.file_count += paths.len(); let lint_rules = get_config_rules_err_empty( lint_options.rules, - member_ctx.maybe_deno_json().map(|c| c.as_ref()), + member_dir.maybe_deno_json().map(|c| c.as_ref()), )?; let incremental_cache = Arc::new(IncrementalCache::new( self.caches.lint_incremental_cache_db(), @@ -282,7 +282,7 @@ impl WorkspaceLinter { if lint_rules.no_slow_types { if self.workspace_module_graph.is_none() { let module_graph_creator = self.module_graph_creator.clone(); - let packages = self.workspace.jsr_packages_for_publish(); + let packages = self.workspace_dir.jsr_packages_for_publish(); self.workspace_module_graph = Some( async move { module_graph_creator @@ -297,7 +297,7 @@ impl WorkspaceLinter { } let workspace_module_graph_future = self.workspace_module_graph.as_ref().unwrap().clone(); - let publish_config = member_ctx.maybe_package_config(); + let publish_config = member_dir.maybe_package_config(); if let Some(publish_config) = publish_config { let has_error = self.has_error.clone(); let reporter_lock = self.reporter_lock.clone(); @@ -989,7 +989,7 @@ fn sort_diagnostics(diagnostics: &mut [JsonLintDiagnostic]) { fn get_config_rules_err_empty( rules: LintRulesConfig, - maybe_config_file: Option<&deno_config::ConfigFile>, + maybe_config_file: Option<&ConfigFile>, ) -> Result { let lint_rules = get_configured_rules(rules, maybe_config_file); if lint_rules.rules.is_empty() { @@ -1026,7 +1026,7 @@ impl ConfiguredRules { pub fn get_configured_rules( rules: LintRulesConfig, - maybe_config_file: Option<&deno_config::ConfigFile>, + maybe_config_file: Option<&ConfigFile>, ) -> ConfiguredRules { const NO_SLOW_TYPES_NAME: &str = "no-slow-types"; let implicit_no_slow_types = @@ -1060,9 +1060,7 @@ pub fn get_configured_rules( } } -fn get_default_tags( - maybe_config_file: Option<&deno_config::ConfigFile>, -) -> Vec { +fn get_default_tags(maybe_config_file: Option<&ConfigFile>) -> Vec { let mut tags = Vec::with_capacity(2); tags.push("recommended".to_string()); if maybe_config_file.map(|c| c.is_package()).unwrap_or(false) { diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs index a22384a528..2e781cceea 100644 --- a/cli/tools/registry/mod.rs +++ b/cli/tools/registry/mod.rs @@ -82,9 +82,9 @@ pub async fn publish( let directory_path = cli_factory.cli_options().initial_cwd(); let cli_options = cli_factory.cli_options(); - let publish_configs = cli_options.workspace.jsr_packages_for_publish(); + let publish_configs = cli_options.start_dir.jsr_packages_for_publish(); if publish_configs.is_empty() { - match cli_options.workspace.resolve_start_ctx().maybe_deno_json() { + match cli_options.start_dir.maybe_deno_json() { Some(deno_json) => { debug_assert!(!deno_json.is_package()); bail!( @@ -437,7 +437,7 @@ impl PublishPreparer { let Some((scope, name_no_scope)) = name_no_at.split_once('/') else { bail!("Invalid package name, use '@/ format"); }; - let file_patterns = package.member_ctx.to_publish_config()?.files; + let file_patterns = package.member_dir.to_publish_config()?.files; let tarball = deno_core::unsync::spawn_blocking({ let diagnostics_collector = diagnostics_collector.clone(); diff --git a/cli/tools/registry/pm.rs b/cli/tools/registry/pm.rs index e3e2f1b558..4573f196db 100644 --- a/cli/tools/registry/pm.rs +++ b/cli/tools/registry/pm.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use std::sync::Arc; use deno_ast::TextChange; -use deno_config::FmtOptionsConfig; +use deno_config::deno_json::FmtOptionsConfig; use deno_core::anyhow::anyhow; use deno_core::anyhow::bail; use deno_core::anyhow::Context; @@ -49,7 +49,7 @@ impl DenoConfigFormat { } enum DenoOrPackageJson { - Deno(Arc, DenoConfigFormat), + Deno(Arc, DenoConfigFormat), Npm(Arc, Option), } @@ -122,9 +122,9 @@ impl DenoOrPackageJson { fn from_flags(flags: Flags) -> Result<(Self, CliFactory), AnyError> { let factory = CliFactory::from_flags(flags.clone())?; let options = factory.cli_options(); - let start_ctx = options.workspace.resolve_start_ctx(); + let start_dir = &options.start_dir; - match (start_ctx.maybe_deno_json(), start_ctx.maybe_pkg_json()) { + match (start_dir.maybe_deno_json(), start_dir.maybe_pkg_json()) { // when both are present, for now, // default to deno.json (Some(deno), Some(_) | None) => Ok(( @@ -140,13 +140,14 @@ impl DenoOrPackageJson { (None, Some(_) | None) => { std::fs::write(options.initial_cwd().join("deno.json"), "{}\n") .context("Failed to create deno.json file")?; + drop(factory); // drop to prevent use log::info!("Created deno.json configuration file."); let factory = CliFactory::from_flags(flags.clone())?; let options = factory.cli_options().clone(); - let start_ctx = options.workspace.resolve_start_ctx(); + let start_dir = &options.start_dir; Ok(( DenoOrPackageJson::Deno( - start_ctx.maybe_deno_json().cloned().ok_or_else(|| { + start_dir.maybe_deno_json().cloned().ok_or_else(|| { anyhow!("config not found, but it was just created") })?, DenoConfigFormat::Json, diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs index 1fbfae4f3f..ee67bb0147 100644 --- a/cli/tools/repl/session.rs +++ b/cli/tools/repl/session.rs @@ -254,7 +254,7 @@ impl ReplSession { )) })?; let ts_config_for_emit = cli_options - .resolve_ts_config_for_emit(deno_config::TsConfigType::Emit)?; + .resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?; let (transpile_options, _) = crate::args::ts_config_to_transpile_and_emit_options( ts_config_for_emit.ts_config, diff --git a/cli/tools/task.rs b/cli/tools/task.rs index 9ab54f2582..d2e16fb121 100644 --- a/cli/tools/task.rs +++ b/cli/tools/task.rs @@ -8,8 +8,9 @@ use crate::factory::CliFactory; use crate::npm::CliNpmResolver; use crate::task_runner; use crate::util::fs::canonicalize_path; +use deno_config::deno_json::Task; use deno_config::workspace::TaskOrScript; -use deno_config::workspace::Workspace; +use deno_config::workspace::WorkspaceDirectory; use deno_config::workspace::WorkspaceTasksConfig; use deno_core::anyhow::bail; use deno_core::anyhow::Context; @@ -30,8 +31,8 @@ pub async fn execute_script( ) -> Result { let factory = CliFactory::from_flags(flags)?; let cli_options = factory.cli_options(); - let start_ctx = cli_options.workspace.resolve_start_ctx(); - if !start_ctx.has_deno_or_pkg_json() { + let start_dir = &cli_options.start_dir; + if !start_dir.has_deno_or_pkg_json() { bail!("deno task couldn't find deno.json(c). See https://deno.land/manual@v{}/getting_started/configuration_file", env!("CARGO_PKG_VERSION")) } let force_use_pkg_json = @@ -44,7 +45,7 @@ pub async fn execute_script( v == "1" }) .unwrap_or(false); - let tasks_config = start_ctx.to_tasks_config()?; + let tasks_config = start_dir.to_tasks_config()?; let tasks_config = if force_use_pkg_json { tasks_config.with_only_pkg_json() } else { @@ -56,7 +57,7 @@ pub async fn execute_script( None => { print_available_tasks( &mut std::io::stdout(), - &cli_options.workspace, + &cli_options.start_dir, &tasks_config, )?; return Ok(1); @@ -143,7 +144,7 @@ pub async fn execute_script( if log::log_enabled!(log::Level::Error) { print_available_tasks( &mut std::io::stderr(), - &cli_options.workspace, + &cli_options.start_dir, &tasks_config, )?; } @@ -204,7 +205,7 @@ fn output_task(task_name: &str, script: &str) { fn print_available_tasks( writer: &mut dyn std::io::Write, - workspace: &Arc, + workspace_dir: &Arc, tasks_config: &WorkspaceTasksConfig, ) -> Result<(), std::io::Error> { writeln!(writer, "{}", colors::green("Available tasks:"))?; @@ -228,7 +229,8 @@ fn print_available_tasks( .as_ref() .map(|config| { let is_root = !is_cwd_root_dir - && config.folder_url == *workspace.root_folder().0.as_ref(); + && config.folder_url + == *workspace_dir.workspace.root_dir().as_ref(); config .tasks .iter() @@ -242,13 +244,10 @@ fn print_available_tasks( .as_ref() .map(|config| { let is_root = !is_cwd_root_dir - && config.folder_url == *workspace.root_folder().0.as_ref(); + && config.folder_url + == *workspace_dir.workspace.root_dir().as_ref(); config.tasks.iter().map(move |(k, v)| { - ( - is_root, - false, - (k, Cow::Owned(deno_config::Task::Definition(v.clone()))), - ) + (is_root, false, (k, Cow::Owned(Task::Definition(v.clone())))) }) }) .into_iter() @@ -275,10 +274,10 @@ fn print_available_tasks( } )?; let definition = match task.as_ref() { - deno_config::Task::Definition(definition) => definition, - deno_config::Task::Commented { definition, .. } => definition, + Task::Definition(definition) => definition, + Task::Commented { definition, .. } => definition, }; - if let deno_config::Task::Commented { comments, .. } = task.as_ref() { + if let Task::Commented { comments, .. } = task.as_ref() { let slash_slash = colors::italic_gray("//"); for comment in comments { writeln!( diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs index bbb796a2a2..73aada7cfe 100644 --- a/cli/tools/vendor/mod.rs +++ b/cli/tools/vendor/mod.rs @@ -53,16 +53,17 @@ pub async fn vendor( validate_options(&mut cli_options, &output_dir)?; let factory = CliFactory::from_cli_options(Arc::new(cli_options)); let cli_options = factory.cli_options(); - if cli_options.workspace.config_folders().len() > 1 { + if cli_options.workspace().config_folders().len() > 1 { bail!("deno vendor is not supported in a workspace. Set `\"vendor\": true` in the workspace deno.json file instead"); } let entry_points = resolve_entry_points(&vendor_flags, cli_options.initial_cwd())?; - let jsx_import_source = - cli_options.workspace.to_maybe_jsx_import_source_config()?; + let jsx_import_source = cli_options + .workspace() + .to_maybe_jsx_import_source_config()?; let module_graph_creator = factory.module_graph_creator().await?.clone(); let workspace_resolver = factory.workspace_resolver().await?; - let root_folder = cli_options.workspace.root_folder().1; + let root_folder = cli_options.workspace().root_folder_configs(); let maybe_config_file = root_folder.deno_json.as_ref(); let output = build::build(build::BuildInput { entry_points, @@ -189,7 +190,7 @@ fn validate_options( let import_map_specifier = options .resolve_specified_import_map_specifier()? .or_else(|| { - let config_file = options.workspace.root_folder().1.deno_json.as_ref()?; + let config_file = options.workspace().root_deno_json()?; config_file .to_import_map_specifier() .ok()