mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
fix(check): support sloppy imports with "compilerOptions.rootDirs" (#27973)
This commit is contained in:
parent
408d581fc1
commit
bc8554878e
28 changed files with 3043 additions and 939 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -1579,9 +1579,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_config"
|
name = "deno_config"
|
||||||
version = "0.47.1"
|
version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f7883c48549bab8e446a58c64ee3d106a13052d2ff5e864de765a60260cb02b"
|
checksum = "6c486df63f7fa0f2142c7eba286c7be87a3cd8c93f66f744fb5853a77cf4347b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"boxed_error",
|
"boxed_error",
|
||||||
"capacity_builder 0.5.0",
|
"capacity_builder 0.5.0",
|
||||||
|
@ -2382,10 +2382,14 @@ dependencies = [
|
||||||
"deno_semver",
|
"deno_semver",
|
||||||
"deno_terminal 0.2.0",
|
"deno_terminal 0.2.0",
|
||||||
"futures",
|
"futures",
|
||||||
|
"import_map",
|
||||||
|
"indexmap 2.3.0",
|
||||||
"log",
|
"log",
|
||||||
"node_resolver",
|
"node_resolver",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sys_traits",
|
"sys_traits",
|
||||||
"test_server",
|
"test_server",
|
||||||
"thiserror 2.0.3",
|
"thiserror 2.0.3",
|
||||||
|
@ -8033,6 +8037,8 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"libc",
|
"libc",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.333.0" }
|
deno_core = { version = "0.333.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.183.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.183.0", path = "./bench_util" }
|
||||||
deno_config = { version = "=0.47.1", features = ["workspace"] }
|
deno_config = { version = "=0.48.0", features = ["workspace"] }
|
||||||
deno_lockfile = "=0.24.0"
|
deno_lockfile = "=0.24.0"
|
||||||
deno_media_type = { version = "=0.2.5", features = ["module_specifier"] }
|
deno_media_type = { version = "=0.2.5", features = ["module_specifier"] }
|
||||||
deno_npm = "=0.27.2"
|
deno_npm = "=0.27.2"
|
||||||
|
@ -155,6 +155,7 @@ hyper = { version = "1.6.0", features = ["full"] }
|
||||||
hyper-rustls = { version = "0.27.2", default-features = false, features = ["http1", "http2", "tls12", "ring"] }
|
hyper-rustls = { version = "0.27.2", default-features = false, features = ["http1", "http2", "tls12", "ring"] }
|
||||||
hyper-util = { version = "0.1.10", features = ["tokio", "client", "client-legacy", "server", "server-auto"] }
|
hyper-util = { version = "0.1.10", features = ["tokio", "client", "client-legacy", "server", "server-auto"] }
|
||||||
hyper_v014 = { package = "hyper", version = "0.14.26", features = ["runtime", "http1"] }
|
hyper_v014 = { package = "hyper", version = "0.14.26", features = ["runtime", "http1"] }
|
||||||
|
import_map = { version = "0.21.0", features = ["ext"] }
|
||||||
indexmap = { version = "2", features = ["serde"] }
|
indexmap = { version = "2", features = ["serde"] }
|
||||||
ipnet = "2.3"
|
ipnet = "2.3"
|
||||||
jsonc-parser = { version = "=0.26.2", features = ["serde"] }
|
jsonc-parser = { version = "=0.26.2", features = ["serde"] }
|
||||||
|
|
|
@ -9,7 +9,6 @@ use std::sync::Arc;
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
use deno_config::workspace::Workspace;
|
use deno_config::workspace::Workspace;
|
||||||
use deno_config::workspace::WorkspaceDirectory;
|
use deno_config::workspace::WorkspaceDirectory;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
|
@ -38,6 +37,7 @@ use deno_resolver::factory::ResolverFactoryOptions;
|
||||||
use deno_resolver::factory::SpecifiedImportMapProvider;
|
use deno_resolver::factory::SpecifiedImportMapProvider;
|
||||||
use deno_resolver::npm::managed::NpmResolutionCell;
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_fs::RealFs;
|
use deno_runtime::deno_fs::RealFs;
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
|
@ -97,7 +97,6 @@ use crate::resolver::CliDenoResolver;
|
||||||
use crate::resolver::CliNpmGraphResolver;
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliNpmReqResolver;
|
use crate::resolver::CliNpmReqResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::resolver::FoundPackageJsonDepFlag;
|
use crate::resolver::FoundPackageJsonDepFlag;
|
||||||
use crate::standalone::binary::DenoCompileBinaryWriter;
|
use crate::standalone::binary::DenoCompileBinaryWriter;
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
@ -160,7 +159,8 @@ struct CliSpecifiedImportMapProvider {
|
||||||
impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
||||||
async fn get(
|
async fn get(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<deno_config::workspace::SpecifiedImportMap>, AnyError> {
|
) -> Result<Option<deno_resolver::workspace::SpecifiedImportMap>, AnyError>
|
||||||
|
{
|
||||||
async fn resolve_import_map_value_from_specifier(
|
async fn resolve_import_map_value_from_specifier(
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
file_fetcher: &CliFileFetcher,
|
file_fetcher: &CliFileFetcher,
|
||||||
|
@ -189,7 +189,7 @@ impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("Unable to load '{}' import map", specifier)
|
format!("Unable to load '{}' import map", specifier)
|
||||||
})?;
|
})?;
|
||||||
Ok(Some(deno_config::workspace::SpecifiedImportMap {
|
Ok(Some(deno_resolver::workspace::SpecifiedImportMap {
|
||||||
base_url: specifier,
|
base_url: specifier,
|
||||||
value,
|
value,
|
||||||
}))
|
}))
|
||||||
|
@ -199,7 +199,7 @@ impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
||||||
self.workspace_external_import_map_loader.get_or_load()?
|
self.workspace_external_import_map_loader.get_or_load()?
|
||||||
{
|
{
|
||||||
let path_url = deno_path_util::url_from_file_path(&import_map.path)?;
|
let path_url = deno_path_util::url_from_file_path(&import_map.path)?;
|
||||||
Ok(Some(deno_config::workspace::SpecifiedImportMap {
|
Ok(Some(deno_resolver::workspace::SpecifiedImportMap {
|
||||||
base_url: path_url,
|
base_url: path_url,
|
||||||
value: import_map.value.clone(),
|
value: import_map.value.clone(),
|
||||||
}))
|
}))
|
||||||
|
@ -646,7 +646,6 @@ impl CliFactory {
|
||||||
ResolverFactoryOptions {
|
ResolverFactoryOptions {
|
||||||
conditions_from_resolution_mode: Default::default(),
|
conditions_from_resolution_mode: Default::default(),
|
||||||
node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)),
|
node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)),
|
||||||
no_sloppy_imports_cache: false,
|
|
||||||
npm_system_info: self.flags.subcommand.npm_system_info(),
|
npm_system_info: self.flags.subcommand.npm_system_info(),
|
||||||
specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider {
|
specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider {
|
||||||
cli_options: self.cli_options()?.clone(),
|
cli_options: self.cli_options()?.clone(),
|
||||||
|
@ -663,7 +662,7 @@ impl CliFactory {
|
||||||
DenoSubcommand::Publish(_) => {
|
DenoSubcommand::Publish(_) => {
|
||||||
// the node_modules directory is not published to jsr, so resolve
|
// the node_modules directory is not published to jsr, so resolve
|
||||||
// dependencies via the package.json rather than using node resolution
|
// dependencies via the package.json rather than using node resolution
|
||||||
Some(deno_config::workspace::PackageJsonDepResolution::Enabled)
|
Some(deno_resolver::workspace::PackageJsonDepResolution::Enabled)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
@ -672,12 +671,6 @@ impl CliFactory {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sloppy_imports_resolver(
|
|
||||||
&self,
|
|
||||||
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
|
|
||||||
self.resolver_factory()?.sloppy_imports_resolver()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn workspace(&self) -> Result<&Arc<Workspace>, AnyError> {
|
pub fn workspace(&self) -> Result<&Arc<Workspace>, AnyError> {
|
||||||
Ok(&self.workspace_directory()?.workspace)
|
Ok(&self.workspace_directory()?.workspace)
|
||||||
}
|
}
|
||||||
|
@ -790,10 +783,9 @@ impl CliFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn lint_rule_provider(&self) -> Result<LintRuleProvider, AnyError> {
|
pub async fn lint_rule_provider(&self) -> Result<LintRuleProvider, AnyError> {
|
||||||
Ok(LintRuleProvider::new(
|
Ok(LintRuleProvider::new(Some(
|
||||||
self.sloppy_imports_resolver()?.cloned(),
|
self.workspace_resolver().await?.clone(),
|
||||||
Some(self.workspace_resolver().await?.clone()),
|
)))
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> {
|
pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> {
|
||||||
|
|
|
@ -34,8 +34,7 @@ use deno_graph::SpecifierError;
|
||||||
use deno_graph::WorkspaceFastCheckOption;
|
use deno_graph::WorkspaceFastCheckOption;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::sloppy_imports_resolve;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_semver::jsr::JsrDepPackageReq;
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
|
@ -62,7 +61,6 @@ use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CliCjsTracker;
|
use crate::resolver::CliCjsTracker;
|
||||||
use crate::resolver::CliNpmGraphResolver;
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::check;
|
use crate::tools::check;
|
||||||
use crate::tools::check::CheckError;
|
use crate::tools::check::CheckError;
|
||||||
|
@ -949,11 +947,14 @@ pub fn maybe_additional_sloppy_imports_message(
|
||||||
sys: &CliSys,
|
sys: &CliSys,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
|
let (resolved, sloppy_reason) = sloppy_imports_resolve(
|
||||||
|
specifier,
|
||||||
|
deno_resolver::workspace::ResolutionKind::Execution,
|
||||||
|
sys.clone(),
|
||||||
|
)?;
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(sys.clone()))
|
sloppy_reason.suggestion_message_for_specifier(&resolved),
|
||||||
.resolve(specifier, SloppyImportsResolutionKind::Execution)?
|
|
||||||
.as_suggestion_message(),
|
|
||||||
RUN_WITH_SLOPPY_IMPORTS_MSG
|
RUN_WITH_SLOPPY_IMPORTS_MSG
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_media_type::MediaType;
|
use deno_media_type::MediaType;
|
||||||
|
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
use deno_runtime::deno_permissions::PermissionsOptions;
|
||||||
use deno_runtime::deno_telemetry::OtelConfig;
|
use deno_runtime::deno_telemetry::OtelConfig;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
|
|
|
@ -9,7 +9,6 @@ use std::path::Path;
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
use deno_ast::SourceRangedForSpanned;
|
use deno_ast::SourceRangedForSpanned;
|
||||||
use deno_ast::SourceTextInfo;
|
use deno_ast::SourceTextInfo;
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde::Serialize;
|
use deno_core::serde::Serialize;
|
||||||
|
@ -20,6 +19,7 @@ use deno_error::JsErrorBox;
|
||||||
use deno_lint::diagnostic::LintDiagnosticRange;
|
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_resolver::npm::managed::NpmResolutionCell;
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
use deno_resolver::workspace::MappedResolution;
|
||||||
use deno_runtime::deno_node::PathClean;
|
use deno_runtime::deno_node::PathClean;
|
||||||
use deno_semver::jsr::JsrPackageNvReference;
|
use deno_semver::jsr::JsrPackageNvReference;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
@ -1348,11 +1348,10 @@ impl CodeActionCollection {
|
||||||
let npm_ref = if let Ok(resolution) = workspace_resolver.resolve(
|
let npm_ref = if let Ok(resolution) = workspace_resolver.resolve(
|
||||||
&dep_key,
|
&dep_key,
|
||||||
document.specifier(),
|
document.specifier(),
|
||||||
deno_config::workspace::ResolutionKind::Execution,
|
deno_resolver::workspace::ResolutionKind::Execution,
|
||||||
) {
|
) {
|
||||||
let specifier = match resolution {
|
let specifier = match resolution {
|
||||||
MappedResolution::Normal { specifier, .. }
|
MappedResolution::Normal { specifier, .. } => specifier,
|
||||||
| MappedResolution::ImportMap { specifier, .. } => specifier,
|
|
||||||
_ => {
|
_ => {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,12 @@ use deno_config::deno_json::TsConfig;
|
||||||
use deno_config::deno_json::TsConfigWithIgnoredOptions;
|
use deno_config::deno_json::TsConfigWithIgnoredOptions;
|
||||||
use deno_config::glob::FilePatterns;
|
use deno_config::glob::FilePatterns;
|
||||||
use deno_config::glob::PathOrPatternSet;
|
use deno_config::glob::PathOrPatternSet;
|
||||||
use deno_config::workspace::CreateResolverOptions;
|
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::SpecifiedImportMap;
|
|
||||||
use deno_config::workspace::VendorEnablement;
|
use deno_config::workspace::VendorEnablement;
|
||||||
use deno_config::workspace::Workspace;
|
use deno_config::workspace::Workspace;
|
||||||
use deno_config::workspace::WorkspaceCache;
|
use deno_config::workspace::WorkspaceCache;
|
||||||
use deno_config::workspace::WorkspaceDirectory;
|
use deno_config::workspace::WorkspaceDirectory;
|
||||||
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
||||||
use deno_config::workspace::WorkspaceDiscoverOptions;
|
use deno_config::workspace::WorkspaceDiscoverOptions;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
@ -49,7 +45,12 @@ use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_package_json::PackageJsonCache;
|
use deno_package_json::PackageJsonCache;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_resolver::npmrc::discover_npmrc_from_workspace;
|
use deno_resolver::npmrc::discover_npmrc_from_workspace;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::CreateResolverOptions;
|
||||||
|
use deno_resolver::workspace::FsCacheOptions;
|
||||||
|
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||||
|
use deno_resolver::workspace::SloppyImportsOptions;
|
||||||
|
use deno_resolver::workspace::SpecifiedImportMap;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use lsp_types::ClientCapabilities;
|
use lsp_types::ClientCapabilities;
|
||||||
|
@ -65,7 +66,6 @@ use crate::args::LintFlags;
|
||||||
use crate::args::LintOptions;
|
use crate::args::LintOptions;
|
||||||
use crate::file_fetcher::CliFileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
use crate::tools::lint::CliLinterOptions;
|
use crate::tools::lint::CliLinterOptions;
|
||||||
|
@ -1206,7 +1206,6 @@ pub struct ConfigData {
|
||||||
pub lockfile: Option<Arc<CliLockfile>>,
|
pub lockfile: Option<Arc<CliLockfile>>,
|
||||||
pub npmrc: Option<Arc<ResolvedNpmRc>>,
|
pub npmrc: Option<Arc<ResolvedNpmRc>>,
|
||||||
pub resolver: Arc<WorkspaceResolver<CliSys>>,
|
pub resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||||
pub sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
pub import_map_from_settings: Option<ModuleSpecifier>,
|
pub import_map_from_settings: Option<ModuleSpecifier>,
|
||||||
pub unstable: BTreeSet<String>,
|
pub unstable: BTreeSet<String>,
|
||||||
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
||||||
|
@ -1569,35 +1568,52 @@ impl ConfigData {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let resolver = member_dir
|
let unstable = member_dir
|
||||||
.workspace
|
.workspace
|
||||||
.create_resolver(
|
.unstable_features()
|
||||||
CliSys::default(),
|
.iter()
|
||||||
CreateResolverOptions {
|
.chain(settings.unstable.as_deref())
|
||||||
pkg_json_dep_resolution,
|
.cloned()
|
||||||
specified_import_map,
|
.collect::<BTreeSet<_>>();
|
||||||
|
let unstable_sloppy_imports = std::env::var("DENO_UNSTABLE_SLOPPY_IMPORTS")
|
||||||
|
.is_ok()
|
||||||
|
|| unstable.contains("sloppy-imports");
|
||||||
|
let resolver = WorkspaceResolver::from_workspace(
|
||||||
|
&member_dir.workspace,
|
||||||
|
CliSys::default(),
|
||||||
|
CreateResolverOptions {
|
||||||
|
pkg_json_dep_resolution,
|
||||||
|
specified_import_map,
|
||||||
|
sloppy_imports_options: if unstable_sloppy_imports {
|
||||||
|
SloppyImportsOptions::Enabled
|
||||||
|
} else {
|
||||||
|
SloppyImportsOptions::Disabled
|
||||||
},
|
},
|
||||||
|
fs_cache_options: FsCacheOptions::Disabled,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.inspect_err(|err| {
|
||||||
|
lsp_warn!(
|
||||||
|
" Failed to load resolver: {}",
|
||||||
|
err // will contain the specifier
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
// create a dummy resolver
|
||||||
|
WorkspaceResolver::new_raw(
|
||||||
|
scope.clone(),
|
||||||
|
None,
|
||||||
|
member_dir.workspace.resolver_jsr_pkgs().collect(),
|
||||||
|
member_dir.workspace.package_jsons().cloned().collect(),
|
||||||
|
pkg_json_dep_resolution,
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
CliSys::default(),
|
||||||
)
|
)
|
||||||
.inspect_err(|err| {
|
});
|
||||||
lsp_warn!(
|
|
||||||
" Failed to load resolver: {}",
|
|
||||||
err // will contain the specifier
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
// create a dummy resolver
|
|
||||||
WorkspaceResolver::new_raw(
|
|
||||||
scope.clone(),
|
|
||||||
None,
|
|
||||||
member_dir.workspace.resolver_jsr_pkgs().collect(),
|
|
||||||
member_dir.workspace.package_jsons().cloned().collect(),
|
|
||||||
pkg_json_dep_resolution,
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
CliSys::default(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
if !resolver.diagnostics().is_empty() {
|
if !resolver.diagnostics().is_empty() {
|
||||||
lsp_warn!(
|
lsp_warn!(
|
||||||
" Resolver diagnostics:\n{}",
|
" Resolver diagnostics:\n{}",
|
||||||
|
@ -1609,26 +1625,8 @@ impl ConfigData {
|
||||||
.join("\n")
|
.join("\n")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let unstable = member_dir
|
|
||||||
.workspace
|
|
||||||
.unstable_features()
|
|
||||||
.iter()
|
|
||||||
.chain(settings.unstable.as_deref())
|
|
||||||
.cloned()
|
|
||||||
.collect::<BTreeSet<_>>();
|
|
||||||
let unstable_sloppy_imports = std::env::var("DENO_UNSTABLE_SLOPPY_IMPORTS")
|
|
||||||
.is_ok()
|
|
||||||
|| unstable.contains("sloppy-imports");
|
|
||||||
let sloppy_imports_resolver = unstable_sloppy_imports.then(|| {
|
|
||||||
Arc::new(CliSloppyImportsResolver::new(
|
|
||||||
SloppyImportsCachedFs::new_without_stat_cache(CliSys::default()),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
let resolver = Arc::new(resolver);
|
let resolver = Arc::new(resolver);
|
||||||
let lint_rule_provider = LintRuleProvider::new(
|
let lint_rule_provider = LintRuleProvider::new(Some(resolver.clone()));
|
||||||
sloppy_imports_resolver.clone(),
|
|
||||||
Some(resolver.clone()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let lint_options = LintOptions::resolve(
|
let lint_options = LintOptions::resolve(
|
||||||
member_dir.dir_path(),
|
member_dir.dir_path(),
|
||||||
|
@ -1676,7 +1674,6 @@ impl ConfigData {
|
||||||
canonicalized_scope,
|
canonicalized_scope,
|
||||||
member_dir,
|
member_dir,
|
||||||
resolver,
|
resolver,
|
||||||
sloppy_imports_resolver,
|
|
||||||
fmt_config,
|
fmt_config,
|
||||||
lint_config,
|
lint_config,
|
||||||
test_config,
|
test_config,
|
||||||
|
|
|
@ -27,9 +27,7 @@ use deno_graph::Resolution;
|
||||||
use deno_graph::ResolutionError;
|
use deno_graph::ResolutionError;
|
||||||
use deno_graph::SpecifierError;
|
use deno_graph::SpecifierError;
|
||||||
use deno_lint::linter::LintConfig as DenoLintConfig;
|
use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::sloppy_imports_resolve;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::tokio_util::create_basic_runtime;
|
use deno_runtime::tokio_util::create_basic_runtime;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
@ -64,7 +62,6 @@ use crate::graph_util;
|
||||||
use crate::graph_util::enhanced_resolution_error_message;
|
use crate::graph_util::enhanced_resolution_error_message;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
use crate::tools::lint::CliLinterOptions;
|
use crate::tools::lint::CliLinterOptions;
|
||||||
|
@ -1013,7 +1010,7 @@ fn generate_lint_diagnostics(
|
||||||
Arc::new(LintConfig::new_with_base(PathBuf::from("/"))),
|
Arc::new(LintConfig::new_with_base(PathBuf::from("/"))),
|
||||||
Arc::new(CliLinter::new(CliLinterOptions {
|
Arc::new(CliLinter::new(CliLinterOptions {
|
||||||
configured_rules: {
|
configured_rules: {
|
||||||
let lint_rule_provider = LintRuleProvider::new(None, None);
|
let lint_rule_provider = LintRuleProvider::new(None);
|
||||||
lint_rule_provider.resolve_lint_rules(Default::default(), None)
|
lint_rule_provider.resolve_lint_rules(Default::default(), None)
|
||||||
},
|
},
|
||||||
fix: false,
|
fix: false,
|
||||||
|
@ -1443,14 +1440,14 @@ impl DenoDiagnostic {
|
||||||
pub fn to_lsp_diagnostic(&self, range: &lsp::Range) -> lsp::Diagnostic {
|
pub fn to_lsp_diagnostic(&self, range: &lsp::Range) -> lsp::Diagnostic {
|
||||||
fn no_local_message(
|
fn no_local_message(
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_sloppy_resolution: Option<&SloppyImportsResolution>,
|
suggestion_message: Option<String>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut message = format!(
|
let mut message = format!(
|
||||||
"Unable to load a local module: {}\n",
|
"Unable to load a local module: {}\n",
|
||||||
to_percent_decoded_str(specifier.as_ref())
|
to_percent_decoded_str(specifier.as_ref())
|
||||||
);
|
);
|
||||||
if let Some(res) = maybe_sloppy_resolution {
|
if let Some(suggestion_message) = suggestion_message {
|
||||||
message.push_str(&res.as_suggestion_message());
|
message.push_str(&suggestion_message);
|
||||||
message.push('.');
|
message.push('.');
|
||||||
} else {
|
} else {
|
||||||
message.push_str("Please check the file path.");
|
message.push_str("Please check the file path.");
|
||||||
|
@ -1467,17 +1464,15 @@ impl DenoDiagnostic {
|
||||||
Self::NotInstalledJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("JSR package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
Self::NotInstalledJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("JSR package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
||||||
Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("npm package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("npm package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
||||||
Self::NoLocal(specifier) => {
|
Self::NoLocal(specifier) => {
|
||||||
let maybe_sloppy_resolution = CliSloppyImportsResolver::new(
|
let sloppy_resolution = sloppy_imports_resolve(specifier, deno_resolver::workspace::ResolutionKind::Execution, CliSys::default());
|
||||||
SloppyImportsCachedFs::new(CliSys::default())
|
let data = sloppy_resolution.as_ref().map(|(resolved, sloppy_reason)| {
|
||||||
).resolve(specifier, SloppyImportsResolutionKind::Execution);
|
|
||||||
let data = maybe_sloppy_resolution.as_ref().map(|res| {
|
|
||||||
json!({
|
json!({
|
||||||
"specifier": specifier,
|
"specifier": specifier,
|
||||||
"to": res.as_specifier(),
|
"to": resolved,
|
||||||
"message": res.as_quick_fix_message(),
|
"message": sloppy_reason.quick_fix_message_for_specifier(resolved),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
(lsp::DiagnosticSeverity::ERROR, no_local_message(specifier, maybe_sloppy_resolution.as_ref()), data)
|
(lsp::DiagnosticSeverity::ERROR, no_local_message(specifier, sloppy_resolution.as_ref().map(|(resolved, sloppy_reason)| sloppy_reason.suggestion_message_for_specifier(resolved))), data)
|
||||||
},
|
},
|
||||||
Self::Redirect { from, to} => (lsp::DiagnosticSeverity::INFORMATION, format!("The import of \"{from}\" was redirected to \"{to}\"."), Some(json!({ "specifier": from, "redirect": to }))),
|
Self::Redirect { from, to} => (lsp::DiagnosticSeverity::INFORMATION, format!("The import of \"{from}\" was redirected to \"{to}\"."), Some(json!({ "specifier": from, "redirect": to }))),
|
||||||
Self::ResolutionError(err) => {
|
Self::ResolutionError(err) => {
|
||||||
|
|
|
@ -12,8 +12,6 @@ use deno_ast::MediaType;
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
use deno_cache_dir::HttpCache;
|
use deno_cache_dir::HttpCache;
|
||||||
use deno_config::deno_json::JsxImportSourceConfig;
|
use deno_config::deno_json::JsxImportSourceConfig;
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_graph::GraphImport;
|
use deno_graph::GraphImport;
|
||||||
|
@ -29,6 +27,8 @@ use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
use deno_resolver::npmrc::create_default_npmrc;
|
use deno_resolver::npmrc::create_default_npmrc;
|
||||||
|
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use deno_resolver::DenoResolverOptions;
|
use deno_resolver::DenoResolverOptions;
|
||||||
use deno_resolver::NodeAndNpmReqResolver;
|
use deno_resolver::NodeAndNpmReqResolver;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
@ -844,9 +844,6 @@ impl<'a> ResolverFactory<'a> {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
sloppy_imports_resolver: self
|
|
||||||
.config_data
|
|
||||||
.and_then(|d| d.sloppy_imports_resolver.clone()),
|
|
||||||
workspace_resolver: self
|
workspace_resolver: self
|
||||||
.config_data
|
.config_data
|
||||||
.map(|d| d.resolver.clone())
|
.map(|d| d.resolver.clone())
|
||||||
|
@ -860,6 +857,8 @@ impl<'a> ResolverFactory<'a> {
|
||||||
PackageJsonDepResolution::Disabled,
|
PackageJsonDepResolution::Disabled,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
self.sys.clone(),
|
self.sys.clone(),
|
||||||
))
|
))
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -4,8 +4,6 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use dashmap::DashSet;
|
use dashmap::DashSet;
|
||||||
use deno_config::workspace::MappedResolutionDiagnostic;
|
|
||||||
use deno_config::workspace::MappedResolutionError;
|
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_graph::source::ResolveError;
|
use deno_graph::source::ResolveError;
|
||||||
|
@ -14,8 +12,8 @@ use deno_graph::NpmLoadError;
|
||||||
use deno_graph::NpmResolvePkgReqsResult;
|
use deno_graph::NpmResolvePkgReqsResult;
|
||||||
use deno_npm::resolution::NpmResolutionError;
|
use deno_npm::resolution::NpmResolutionError;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::MappedResolutionDiagnostic;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolver;
|
use deno_resolver::workspace::MappedResolutionError;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
use deno_runtime::deno_node::is_builtin_node_module;
|
use deno_runtime::deno_node::is_builtin_node_module;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
@ -35,14 +33,10 @@ pub type CliCjsTracker =
|
||||||
deno_resolver::cjs::CjsTracker<DenoInNpmPackageChecker, CliSys>;
|
deno_resolver::cjs::CjsTracker<DenoInNpmPackageChecker, CliSys>;
|
||||||
pub type CliIsCjsResolver =
|
pub type CliIsCjsResolver =
|
||||||
deno_resolver::cjs::IsCjsResolver<DenoInNpmPackageChecker, CliSys>;
|
deno_resolver::cjs::IsCjsResolver<DenoInNpmPackageChecker, CliSys>;
|
||||||
pub type CliSloppyImportsCachedFs = SloppyImportsCachedFs<CliSys>;
|
|
||||||
pub type CliSloppyImportsResolver =
|
|
||||||
SloppyImportsResolver<CliSloppyImportsCachedFs>;
|
|
||||||
pub type CliDenoResolver = deno_resolver::DenoResolver<
|
pub type CliDenoResolver = deno_resolver::DenoResolver<
|
||||||
DenoInNpmPackageChecker,
|
DenoInNpmPackageChecker,
|
||||||
DenoIsBuiltInNodeModuleChecker,
|
DenoIsBuiltInNodeModuleChecker,
|
||||||
CliNpmResolver,
|
CliNpmResolver,
|
||||||
CliSloppyImportsCachedFs,
|
|
||||||
CliSys,
|
CliSys,
|
||||||
>;
|
>;
|
||||||
pub type CliNpmReqResolver = deno_resolver::npm::NpmReqResolver<
|
pub type CliNpmReqResolver = deno_resolver::npm::NpmReqResolver<
|
||||||
|
|
|
@ -7,9 +7,7 @@ use std::sync::Arc;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::ModuleLoaderError;
|
use deno_core::error::ModuleLoaderError;
|
||||||
use deno_core::futures::future::LocalBoxFuture;
|
use deno_core::futures::future::LocalBoxFuture;
|
||||||
|
@ -59,9 +57,9 @@ use deno_resolver::npm::NpmReqResolver;
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
use deno_resolver::npm::NpmResolver;
|
use deno_resolver::npm::NpmResolver;
|
||||||
use deno_resolver::npm::NpmResolverCreateOptions;
|
use deno_resolver::npm::NpmResolverCreateOptions;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::MappedResolution;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
use deno_resolver::workspace::SloppyImportsOptions;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolver;
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use deno_runtime::code_cache::CodeCache;
|
use deno_runtime::code_cache::CodeCache;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::create_host_defined_options;
|
use deno_runtime::deno_node::create_host_defined_options;
|
||||||
|
@ -107,8 +105,6 @@ struct SharedModuleLoaderState {
|
||||||
npm_module_loader: Arc<DenoRtNpmModuleLoader>,
|
npm_module_loader: Arc<DenoRtNpmModuleLoader>,
|
||||||
npm_registry_permission_checker: NpmRegistryReadPermissionChecker<DenoRtSys>,
|
npm_registry_permission_checker: NpmRegistryReadPermissionChecker<DenoRtSys>,
|
||||||
npm_req_resolver: Arc<DenoRtNpmReqResolver>,
|
npm_req_resolver: Arc<DenoRtNpmReqResolver>,
|
||||||
sloppy_imports_resolver:
|
|
||||||
Option<SloppyImportsResolver<SloppyImportsCachedFs<DenoRtSys>>>,
|
|
||||||
vfs: Arc<FileBackedVfs>,
|
vfs: Arc<FileBackedVfs>,
|
||||||
workspace_resolver: WorkspaceResolver<DenoRtSys>,
|
workspace_resolver: WorkspaceResolver<DenoRtSys>,
|
||||||
}
|
}
|
||||||
|
@ -210,7 +206,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
let mapped_resolution = self.shared.workspace_resolver.resolve(
|
let mapped_resolution = self.shared.workspace_resolver.resolve(
|
||||||
raw_specifier,
|
raw_specifier,
|
||||||
&referrer,
|
&referrer,
|
||||||
deno_config::workspace::ResolutionKind::Execution,
|
deno_resolver::workspace::ResolutionKind::Execution,
|
||||||
);
|
);
|
||||||
|
|
||||||
match mapped_resolution {
|
match mapped_resolution {
|
||||||
|
@ -289,8 +285,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Ok(MappedResolution::Normal { specifier, .. })
|
Ok(MappedResolution::Normal { specifier, .. }) => {
|
||||||
| Ok(MappedResolution::ImportMap { specifier, .. }) => {
|
|
||||||
if let Ok(reference) =
|
if let Ok(reference) =
|
||||||
NpmPackageReqReference::from_specifier(&specifier)
|
NpmPackageReqReference::from_specifier(&specifier)
|
||||||
{
|
{
|
||||||
|
@ -322,18 +317,6 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do sloppy imports resolution if enabled
|
|
||||||
let specifier = if let Some(sloppy_imports_resolver) =
|
|
||||||
&self.shared.sloppy_imports_resolver
|
|
||||||
{
|
|
||||||
sloppy_imports_resolver
|
|
||||||
.resolve(&specifier, SloppyImportsResolutionKind::Execution)
|
|
||||||
.map(|s| s.into_specifier())
|
|
||||||
.unwrap_or(specifier)
|
|
||||||
} else {
|
|
||||||
specifier
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
self
|
self
|
||||||
.shared
|
.shared
|
||||||
|
@ -832,10 +815,6 @@ pub async fn run(
|
||||||
pkg_json_resolver.clone(),
|
pkg_json_resolver.clone(),
|
||||||
sys.clone(),
|
sys.clone(),
|
||||||
));
|
));
|
||||||
let sloppy_imports_resolver =
|
|
||||||
metadata.unstable_config.sloppy_imports.then(|| {
|
|
||||||
SloppyImportsResolver::new(SloppyImportsCachedFs::new(sys.clone()))
|
|
||||||
});
|
|
||||||
let workspace_resolver = {
|
let workspace_resolver = {
|
||||||
let import_map = match metadata.workspace_resolver.import_map {
|
let import_map = match metadata.workspace_resolver.import_map {
|
||||||
Some(import_map) => Some(
|
Some(import_map) => Some(
|
||||||
|
@ -883,6 +862,12 @@ pub async fn run(
|
||||||
.collect(),
|
.collect(),
|
||||||
pkg_jsons,
|
pkg_jsons,
|
||||||
metadata.workspace_resolver.pkg_json_resolution,
|
metadata.workspace_resolver.pkg_json_resolution,
|
||||||
|
if metadata.unstable_config.sloppy_imports {
|
||||||
|
SloppyImportsOptions::Enabled
|
||||||
|
} else {
|
||||||
|
SloppyImportsOptions::Disabled
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
sys.clone(),
|
sys.clone(),
|
||||||
|
@ -915,7 +900,6 @@ pub async fn run(
|
||||||
)),
|
)),
|
||||||
npm_registry_permission_checker,
|
npm_registry_permission_checker,
|
||||||
npm_req_resolver,
|
npm_req_resolver,
|
||||||
sloppy_imports_resolver,
|
|
||||||
vfs: vfs.clone(),
|
vfs: vfs.clone(),
|
||||||
workspace_resolver,
|
workspace_resolver,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -16,7 +16,6 @@ use capacity_builder::BytesAppendable;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_ast::ModuleKind;
|
use deno_ast::ModuleKind;
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -49,6 +48,7 @@ use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_path_util::url_from_directory_path;
|
use deno_path_util::url_from_directory_path;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use node_resolver::analyze::CjsAnalysis;
|
use node_resolver::analyze::CjsAnalysis;
|
||||||
use node_resolver::analyze::CjsCodeAnalyzer;
|
use node_resolver::analyze::CjsCodeAnalyzer;
|
||||||
|
|
|
@ -59,21 +59,18 @@ pub async fn info(
|
||||||
let maybe_import_specifier = if let Ok(resolved) = resolver.resolve(
|
let maybe_import_specifier = if let Ok(resolved) = resolver.resolve(
|
||||||
&specifier,
|
&specifier,
|
||||||
&cwd_url,
|
&cwd_url,
|
||||||
deno_config::workspace::ResolutionKind::Execution,
|
deno_resolver::workspace::ResolutionKind::Execution,
|
||||||
) {
|
) {
|
||||||
match resolved {
|
match resolved {
|
||||||
deno_config::workspace::MappedResolution::Normal {
|
deno_resolver::workspace::MappedResolution::Normal {
|
||||||
specifier, ..
|
|
||||||
}
|
|
||||||
| deno_config::workspace::MappedResolution::ImportMap {
|
|
||||||
specifier,
|
specifier,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| deno_config::workspace::MappedResolution::WorkspaceJsrPackage {
|
| deno_resolver::workspace::MappedResolution::WorkspaceJsrPackage {
|
||||||
specifier,
|
specifier,
|
||||||
..
|
..
|
||||||
} => Some(specifier),
|
} => Some(specifier),
|
||||||
deno_config::workspace::MappedResolution::WorkspaceNpmPackage {
|
deno_resolver::workspace::MappedResolution::WorkspaceNpmPackage {
|
||||||
target_pkg_json,
|
target_pkg_json,
|
||||||
sub_path,
|
sub_path,
|
||||||
..
|
..
|
||||||
|
@ -88,7 +85,7 @@ pub async fn info(
|
||||||
)?
|
)?
|
||||||
.into_url()?,
|
.into_url()?,
|
||||||
),
|
),
|
||||||
deno_config::workspace::MappedResolution::PackageJson {
|
deno_resolver::workspace::MappedResolution::PackageJson {
|
||||||
alias,
|
alias,
|
||||||
sub_path,
|
sub_path,
|
||||||
dep_result,
|
dep_result,
|
||||||
|
|
|
@ -499,7 +499,7 @@ fn collect_lint_files(
|
||||||
|
|
||||||
#[allow(clippy::print_stdout)]
|
#[allow(clippy::print_stdout)]
|
||||||
pub fn print_rules_list(json: bool, maybe_rules_tags: Option<Vec<String>>) {
|
pub fn print_rules_list(json: bool, maybe_rules_tags: Option<Vec<String>>) {
|
||||||
let rule_provider = LintRuleProvider::new(None, None);
|
let rule_provider = LintRuleProvider::new(None);
|
||||||
let mut all_rules = rule_provider.all_rules();
|
let mut all_rules = rule_provider.all_rules();
|
||||||
let configured_rules = rule_provider.resolve_lint_rules(
|
let configured_rules = rule_provider.resolve_lint_rules(
|
||||||
LintRulesConfig {
|
LintRulesConfig {
|
||||||
|
@ -686,7 +686,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all_rules() -> Vec<String> {
|
fn get_all_rules() -> Vec<String> {
|
||||||
let rule_provider = LintRuleProvider::new(None, None);
|
let rule_provider = LintRuleProvider::new(None);
|
||||||
let configured_rules =
|
let configured_rules =
|
||||||
rule_provider.resolve_lint_rules(Default::default(), None);
|
rule_provider.resolve_lint_rules(Default::default(), None);
|
||||||
let mut all_rules = configured_rules
|
let mut all_rules = configured_rules
|
||||||
|
|
|
@ -7,15 +7,14 @@ use std::sync::Arc;
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_config::deno_json::ConfigFile;
|
use deno_config::deno_json::ConfigFile;
|
||||||
use deno_config::deno_json::LintRulesConfig;
|
use deno_config::deno_json::LintRulesConfig;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_lint::diagnostic::LintDiagnostic;
|
use deno_lint::diagnostic::LintDiagnostic;
|
||||||
use deno_lint::rules::LintRule;
|
use deno_lint::rules::LintRule;
|
||||||
use deno_lint::tags;
|
use deno_lint::tags;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
|
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
mod no_sloppy_imports;
|
mod no_sloppy_imports;
|
||||||
|
@ -141,19 +140,14 @@ impl ConfiguredRules {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LintRuleProvider {
|
pub struct LintRuleProvider {
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LintRuleProvider {
|
impl LintRuleProvider {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self { workspace_resolver }
|
||||||
sloppy_imports_resolver,
|
|
||||||
workspace_resolver,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_lint_rules_err_empty(
|
pub fn resolve_lint_rules_err_empty(
|
||||||
|
@ -172,7 +166,6 @@ impl LintRuleProvider {
|
||||||
let deno_lint_rules = deno_lint::rules::get_all_rules();
|
let deno_lint_rules = deno_lint::rules::get_all_rules();
|
||||||
let cli_lint_rules = vec![CliLintRule(CliLintRuleKind::Extended(
|
let cli_lint_rules = vec![CliLintRule(CliLintRuleKind::Extended(
|
||||||
Box::new(no_sloppy_imports::NoSloppyImportsRule::new(
|
Box::new(no_sloppy_imports::NoSloppyImportsRule::new(
|
||||||
self.sloppy_imports_resolver.clone(),
|
|
||||||
self.workspace_resolver.clone(),
|
self.workspace_resolver.clone(),
|
||||||
)),
|
)),
|
||||||
))];
|
))];
|
||||||
|
@ -274,7 +267,7 @@ mod test {
|
||||||
include: None,
|
include: None,
|
||||||
tags: None,
|
tags: None,
|
||||||
};
|
};
|
||||||
let rules_provider = LintRuleProvider::new(None, None);
|
let rules_provider = LintRuleProvider::new(None);
|
||||||
let rules = rules_provider.resolve_lint_rules(rules_config, None);
|
let rules = rules_provider.resolve_lint_rules(rules_config, None);
|
||||||
let mut rule_names = rules
|
let mut rule_names = rules
|
||||||
.rules
|
.rules
|
||||||
|
|
|
@ -6,7 +6,6 @@ use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_graph::source::ResolutionKind;
|
use deno_graph::source::ResolutionKind;
|
||||||
use deno_graph::source::ResolveError;
|
use deno_graph::source::ResolveError;
|
||||||
|
@ -17,31 +16,25 @@ use deno_lint::diagnostic::LintFix;
|
||||||
use deno_lint::diagnostic::LintFixChange;
|
use deno_lint::diagnostic::LintFixChange;
|
||||||
use deno_lint::rules::LintRule;
|
use deno_lint::rules::LintRule;
|
||||||
use deno_lint::tags;
|
use deno_lint::tags;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
use deno_resolver::workspace::SloppyImportsResolutionReason;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use text_lines::LineAndColumnIndex;
|
use text_lines::LineAndColumnIndex;
|
||||||
|
|
||||||
use super::ExtendedLintRule;
|
use super::ExtendedLintRule;
|
||||||
use crate::graph_util::CliJsrUrlProvider;
|
use crate::graph_util::CliJsrUrlProvider;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NoSloppyImportsRule {
|
pub struct NoSloppyImportsRule {
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
// None for making printing out the lint rules easy
|
// None for making printing out the lint rules easy
|
||||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoSloppyImportsRule {
|
impl NoSloppyImportsRule {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
NoSloppyImportsRule {
|
NoSloppyImportsRule { workspace_resolver }
|
||||||
sloppy_imports_resolver,
|
|
||||||
workspace_resolver,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +47,11 @@ impl ExtendedLintRule for NoSloppyImportsRule {
|
||||||
// do sloppy import resolution because sloppy import
|
// do sloppy import resolution because sloppy import
|
||||||
// resolution requires knowing about the surrounding files
|
// resolution requires knowing about the surrounding files
|
||||||
// in addition to the current one
|
// in addition to the current one
|
||||||
self.sloppy_imports_resolver.is_none() || self.workspace_resolver.is_none()
|
let Some(workspace_resolver) = &self.workspace_resolver else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
!workspace_resolver.sloppy_imports_enabled()
|
||||||
|
&& !workspace_resolver.has_compiler_options_root_dirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help_docs_url(&self) -> Cow<'static, str> {
|
fn help_docs_url(&self) -> Cow<'static, str> {
|
||||||
|
@ -75,16 +72,12 @@ impl LintRule for NoSloppyImportsRule {
|
||||||
let Some(workspace_resolver) = &self.workspace_resolver else {
|
let Some(workspace_resolver) = &self.workspace_resolver else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if context.specifier().scheme() != "file" {
|
if context.specifier().scheme() != "file" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolver = SloppyImportCaptureResolver {
|
let resolver = SloppyImportCaptureResolver {
|
||||||
workspace_resolver,
|
workspace_resolver,
|
||||||
sloppy_imports_resolver,
|
|
||||||
captures: Default::default(),
|
captures: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,7 +95,9 @@ impl LintRule for NoSloppyImportsRule {
|
||||||
maybe_npm_resolver: None,
|
maybe_npm_resolver: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (referrer, sloppy_import) in resolver.captures.borrow_mut().drain() {
|
for (referrer, (specifier, sloppy_reason)) in
|
||||||
|
resolver.captures.borrow_mut().drain()
|
||||||
|
{
|
||||||
let start_range =
|
let start_range =
|
||||||
context.text_info().loc_to_source_pos(LineAndColumnIndex {
|
context.text_info().loc_to_source_pos(LineAndColumnIndex {
|
||||||
line_index: referrer.range.start.line,
|
line_index: referrer.range.start.line,
|
||||||
|
@ -126,10 +121,12 @@ impl LintRule for NoSloppyImportsRule {
|
||||||
custom_docs_url: Some(DOCS_URL.to_string()),
|
custom_docs_url: Some(DOCS_URL.to_string()),
|
||||||
fixes: context
|
fixes: context
|
||||||
.specifier()
|
.specifier()
|
||||||
.make_relative(sloppy_import.as_specifier())
|
.make_relative(&specifier)
|
||||||
.map(|relative| {
|
.map(|relative| {
|
||||||
vec![LintFix {
|
vec![LintFix {
|
||||||
description: Cow::Owned(sloppy_import.as_quick_fix_message()),
|
description: Cow::Owned(
|
||||||
|
sloppy_reason.quick_fix_message_for_specifier(&specifier),
|
||||||
|
),
|
||||||
changes: vec![LintFixChange {
|
changes: vec![LintFixChange {
|
||||||
new_text: Cow::Owned({
|
new_text: Cow::Owned({
|
||||||
let relative = if relative.starts_with("../") {
|
let relative = if relative.starts_with("../") {
|
||||||
|
@ -176,8 +173,9 @@ impl LintRule for NoSloppyImportsRule {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SloppyImportCaptureResolver<'a> {
|
struct SloppyImportCaptureResolver<'a> {
|
||||||
workspace_resolver: &'a WorkspaceResolver<CliSys>,
|
workspace_resolver: &'a WorkspaceResolver<CliSys>,
|
||||||
sloppy_imports_resolver: &'a CliSloppyImportsResolver,
|
captures: RefCell<
|
||||||
captures: RefCell<HashMap<Range, SloppyImportsResolution>>,
|
HashMap<Range, (deno_ast::ModuleSpecifier, SloppyImportsResolutionReason)>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> deno_graph::source::Resolver for SloppyImportCaptureResolver<'a> {
|
impl<'a> deno_graph::source::Resolver for SloppyImportCaptureResolver<'a> {
|
||||||
|
@ -194,45 +192,37 @@ impl<'a> deno_graph::source::Resolver for SloppyImportCaptureResolver<'a> {
|
||||||
&referrer_range.specifier,
|
&referrer_range.specifier,
|
||||||
match resolution_kind {
|
match resolution_kind {
|
||||||
ResolutionKind::Execution => {
|
ResolutionKind::Execution => {
|
||||||
deno_config::workspace::ResolutionKind::Execution
|
deno_resolver::workspace::ResolutionKind::Execution
|
||||||
}
|
}
|
||||||
ResolutionKind::Types => {
|
ResolutionKind::Types => {
|
||||||
deno_config::workspace::ResolutionKind::Types
|
deno_resolver::workspace::ResolutionKind::Types
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.map_err(|err| ResolveError::Other(JsErrorBox::from_err(err)))?;
|
.map_err(|err| ResolveError::Other(JsErrorBox::from_err(err)))?;
|
||||||
|
|
||||||
match resolution {
|
match resolution {
|
||||||
deno_config::workspace::MappedResolution::Normal {
|
deno_resolver::workspace::MappedResolution::Normal {
|
||||||
specifier, ..
|
specifier,
|
||||||
}
|
sloppy_reason,
|
||||||
| deno_config::workspace::MappedResolution::ImportMap {
|
..
|
||||||
specifier, ..
|
} => {
|
||||||
} => match self.sloppy_imports_resolver.resolve(
|
if let Some(sloppy_reason) = sloppy_reason {
|
||||||
&specifier,
|
|
||||||
match resolution_kind {
|
|
||||||
ResolutionKind::Execution => SloppyImportsResolutionKind::Execution,
|
|
||||||
ResolutionKind::Types => SloppyImportsResolutionKind::Types,
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Some(res) => {
|
|
||||||
self
|
self
|
||||||
.captures
|
.captures
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.entry(referrer_range.clone())
|
.entry(referrer_range.clone())
|
||||||
.or_insert_with(|| res.clone());
|
.or_insert_with(|| (specifier.clone(), sloppy_reason));
|
||||||
Ok(res.into_specifier())
|
|
||||||
}
|
}
|
||||||
None => Ok(specifier),
|
Ok(specifier)
|
||||||
},
|
}
|
||||||
deno_config::workspace::MappedResolution::WorkspaceJsrPackage {
|
deno_resolver::workspace::MappedResolution::WorkspaceJsrPackage {
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| deno_config::workspace::MappedResolution::WorkspaceNpmPackage {
|
| deno_resolver::workspace::MappedResolution::WorkspaceNpmPackage {
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| deno_config::workspace::MappedResolution::PackageJson { .. } => {
|
| deno_resolver::workspace::MappedResolution::PackageJson { .. } => {
|
||||||
// this error is ignored
|
// this error is ignored
|
||||||
Err(ResolveError::Other(JsErrorBox::generic("")))
|
Err(ResolveError::Other(JsErrorBox::generic("")))
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,6 @@ pub async fn publish(
|
||||||
}
|
}
|
||||||
|
|
||||||
let specifier_unfurler = Arc::new(SpecifierUnfurler::new(
|
let specifier_unfurler = Arc::new(SpecifierUnfurler::new(
|
||||||
cli_factory.sloppy_imports_resolver()?.cloned(),
|
|
||||||
cli_factory.workspace_resolver().await?.clone(),
|
cli_factory.workspace_resolver().await?.clone(),
|
||||||
cli_options.unstable_bare_node_builtins(),
|
cli_options.unstable_bare_node_builtins(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -15,9 +15,6 @@ use deno_ast::ParsedSource;
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
use deno_ast::SourceTextInfo;
|
use deno_ast::SourceTextInfo;
|
||||||
use deno_ast::SourceTextProvider;
|
use deno_ast::SourceTextProvider;
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow;
|
use deno_core::anyhow;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::DependencyDescriptor;
|
use deno_graph::DependencyDescriptor;
|
||||||
|
@ -27,12 +24,13 @@ use deno_graph::StaticDependencyKind;
|
||||||
use deno_graph::TypeScriptReference;
|
use deno_graph::TypeScriptReference;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_package_json::PackageJsonDepWorkspaceReq;
|
use deno_package_json::PackageJsonDepWorkspaceReq;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
use deno_resolver::workspace::MappedResolution;
|
||||||
|
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||||
|
use deno_resolver::workspace::WorkspaceResolver;
|
||||||
use deno_runtime::deno_node::is_builtin_node_module;
|
use deno_runtime::deno_node::is_builtin_node_module;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use deno_semver::VersionReq;
|
use deno_semver::VersionReq;
|
||||||
|
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::sys::CliSys;
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -190,14 +188,12 @@ enum UnfurlSpecifierError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SpecifierUnfurler {
|
pub struct SpecifierUnfurler {
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||||
bare_node_builtins: bool,
|
bare_node_builtins: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifierUnfurler {
|
impl SpecifierUnfurler {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
|
||||||
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||||
bare_node_builtins: bool,
|
bare_node_builtins: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -206,7 +202,6 @@ impl SpecifierUnfurler {
|
||||||
PackageJsonDepResolution::Enabled
|
PackageJsonDepResolution::Enabled
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
sloppy_imports_resolver,
|
|
||||||
workspace_resolver,
|
workspace_resolver,
|
||||||
bare_node_builtins,
|
bare_node_builtins,
|
||||||
}
|
}
|
||||||
|
@ -216,7 +211,7 @@ impl SpecifierUnfurler {
|
||||||
&self,
|
&self,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
resolution_kind: SloppyImportsResolutionKind,
|
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||||
text_info: &SourceTextInfo,
|
text_info: &SourceTextInfo,
|
||||||
range: &deno_graph::PositionRange,
|
range: &deno_graph::PositionRange,
|
||||||
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic),
|
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic),
|
||||||
|
@ -251,16 +246,15 @@ impl SpecifierUnfurler {
|
||||||
&self,
|
&self,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
resolution_kind: SloppyImportsResolutionKind,
|
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||||
) -> Result<Option<String>, UnfurlSpecifierError> {
|
) -> Result<Option<String>, UnfurlSpecifierError> {
|
||||||
let resolved = if let Ok(resolved) = self.workspace_resolver.resolve(
|
let resolved = if let Ok(resolved) =
|
||||||
specifier,
|
self
|
||||||
referrer,
|
.workspace_resolver
|
||||||
resolution_kind.into(),
|
.resolve(specifier, referrer, resolution_kind)
|
||||||
) {
|
{
|
||||||
match resolved {
|
match resolved {
|
||||||
MappedResolution::Normal { specifier, .. }
|
MappedResolution::Normal { specifier, .. } => Some(specifier),
|
||||||
| MappedResolution::ImportMap { specifier, .. } => Some(specifier),
|
|
||||||
MappedResolution::WorkspaceJsrPackage { pkg_req_ref, .. } => {
|
MappedResolution::WorkspaceJsrPackage { pkg_req_ref, .. } => {
|
||||||
Some(ModuleSpecifier::parse(&pkg_req_ref.to_string()).unwrap())
|
Some(ModuleSpecifier::parse(&pkg_req_ref.to_string()).unwrap())
|
||||||
}
|
}
|
||||||
|
@ -398,15 +392,6 @@ impl SpecifierUnfurler {
|
||||||
// } else {
|
// } else {
|
||||||
// resolved
|
// resolved
|
||||||
// };
|
// };
|
||||||
let resolved =
|
|
||||||
if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
|
|
||||||
sloppy_imports_resolver
|
|
||||||
.resolve(&resolved, resolution_kind)
|
|
||||||
.map(|res| res.into_specifier())
|
|
||||||
.unwrap_or(resolved)
|
|
||||||
} else {
|
|
||||||
resolved
|
|
||||||
};
|
|
||||||
let relative_resolved = relative_url(&resolved, referrer);
|
let relative_resolved = relative_url(&resolved, referrer);
|
||||||
if relative_resolved == specifier {
|
if relative_resolved == specifier {
|
||||||
Ok(None) // nothing to unfurl
|
Ok(None) // nothing to unfurl
|
||||||
|
@ -464,7 +449,7 @@ impl SpecifierUnfurler {
|
||||||
let maybe_unfurled = self.unfurl_specifier_reporting_diagnostic(
|
let maybe_unfurled = self.unfurl_specifier_reporting_diagnostic(
|
||||||
module_url,
|
module_url,
|
||||||
specifier,
|
specifier,
|
||||||
SloppyImportsResolutionKind::Execution, // dynamic imports are always execution
|
deno_resolver::workspace::ResolutionKind::Execution, // dynamic imports are always execution
|
||||||
text_info,
|
text_info,
|
||||||
&dep.argument_range,
|
&dep.argument_range,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
|
@ -492,7 +477,7 @@ impl SpecifierUnfurler {
|
||||||
let unfurled = self.unfurl_specifier_reporting_diagnostic(
|
let unfurled = self.unfurl_specifier_reporting_diagnostic(
|
||||||
module_url,
|
module_url,
|
||||||
specifier,
|
specifier,
|
||||||
SloppyImportsResolutionKind::Execution, // dynamic imports are always execution
|
deno_resolver::workspace::ResolutionKind::Execution, // dynamic imports are always execution
|
||||||
text_info,
|
text_info,
|
||||||
&dep.argument_range,
|
&dep.argument_range,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
|
@ -538,7 +523,7 @@ impl SpecifierUnfurler {
|
||||||
let analyze_specifier =
|
let analyze_specifier =
|
||||||
|specifier: &str,
|
|specifier: &str,
|
||||||
range: &deno_graph::PositionRange,
|
range: &deno_graph::PositionRange,
|
||||||
resolution_kind: SloppyImportsResolutionKind,
|
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||||
text_changes: &mut Vec<deno_ast::TextChange>,
|
text_changes: &mut Vec<deno_ast::TextChange>,
|
||||||
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic)| {
|
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic)| {
|
||||||
if let Some(unfurled) = self.unfurl_specifier_reporting_diagnostic(
|
if let Some(unfurled) = self.unfurl_specifier_reporting_diagnostic(
|
||||||
|
@ -559,18 +544,18 @@ impl SpecifierUnfurler {
|
||||||
match dep {
|
match dep {
|
||||||
DependencyDescriptor::Static(dep) => {
|
DependencyDescriptor::Static(dep) => {
|
||||||
let resolution_kind = if parsed_source.media_type().is_declaration() {
|
let resolution_kind = if parsed_source.media_type().is_declaration() {
|
||||||
SloppyImportsResolutionKind::Types
|
deno_resolver::workspace::ResolutionKind::Types
|
||||||
} else {
|
} else {
|
||||||
match dep.kind {
|
match dep.kind {
|
||||||
StaticDependencyKind::Export
|
StaticDependencyKind::Export
|
||||||
| StaticDependencyKind::Import
|
| StaticDependencyKind::Import
|
||||||
| StaticDependencyKind::ExportEquals
|
| StaticDependencyKind::ExportEquals
|
||||||
| StaticDependencyKind::ImportEquals => {
|
| StaticDependencyKind::ImportEquals => {
|
||||||
SloppyImportsResolutionKind::Execution
|
deno_resolver::workspace::ResolutionKind::Execution
|
||||||
}
|
}
|
||||||
StaticDependencyKind::ExportType
|
StaticDependencyKind::ExportType
|
||||||
| StaticDependencyKind::ImportType => {
|
| StaticDependencyKind::ImportType => {
|
||||||
SloppyImportsResolutionKind::Types
|
deno_resolver::workspace::ResolutionKind::Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -616,7 +601,7 @@ impl SpecifierUnfurler {
|
||||||
analyze_specifier(
|
analyze_specifier(
|
||||||
&specifier_with_range.text,
|
&specifier_with_range.text,
|
||||||
&specifier_with_range.range,
|
&specifier_with_range.range,
|
||||||
SloppyImportsResolutionKind::Types,
|
deno_resolver::workspace::ResolutionKind::Types,
|
||||||
&mut text_changes,
|
&mut text_changes,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
);
|
);
|
||||||
|
@ -625,7 +610,7 @@ impl SpecifierUnfurler {
|
||||||
analyze_specifier(
|
analyze_specifier(
|
||||||
&jsdoc.specifier.text,
|
&jsdoc.specifier.text,
|
||||||
&jsdoc.specifier.range,
|
&jsdoc.specifier.range,
|
||||||
SloppyImportsResolutionKind::Types,
|
deno_resolver::workspace::ResolutionKind::Types,
|
||||||
&mut text_changes,
|
&mut text_changes,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
);
|
);
|
||||||
|
@ -634,7 +619,7 @@ impl SpecifierUnfurler {
|
||||||
analyze_specifier(
|
analyze_specifier(
|
||||||
&specifier_with_range.text,
|
&specifier_with_range.text,
|
||||||
&specifier_with_range.range,
|
&specifier_with_range.range,
|
||||||
SloppyImportsResolutionKind::Execution,
|
deno_resolver::workspace::ResolutionKind::Execution,
|
||||||
&mut text_changes,
|
&mut text_changes,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
);
|
);
|
||||||
|
@ -643,7 +628,7 @@ impl SpecifierUnfurler {
|
||||||
analyze_specifier(
|
analyze_specifier(
|
||||||
&specifier_with_range.text,
|
&specifier_with_range.text,
|
||||||
&specifier_with_range.range,
|
&specifier_with_range.range,
|
||||||
SloppyImportsResolutionKind::Types,
|
deno_resolver::workspace::ResolutionKind::Types,
|
||||||
&mut text_changes,
|
&mut text_changes,
|
||||||
diagnostic_reporter,
|
diagnostic_reporter,
|
||||||
);
|
);
|
||||||
|
@ -700,7 +685,7 @@ mod tests {
|
||||||
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
use deno_resolver::workspace::SloppyImportsOptions;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use import_map::ImportMapWithDiagnostics;
|
use import_map::ImportMapWithDiagnostics;
|
||||||
|
@ -760,18 +745,14 @@ mod tests {
|
||||||
exports: IndexMap::from([(".".to_string(), "mod.ts".to_string())]),
|
exports: IndexMap::from([(".".to_string(), "mod.ts".to_string())]),
|
||||||
}],
|
}],
|
||||||
vec![Arc::new(package_json)],
|
vec![Arc::new(package_json)],
|
||||||
deno_config::workspace::PackageJsonDepResolution::Enabled,
|
deno_resolver::workspace::PackageJsonDepResolution::Enabled,
|
||||||
|
SloppyImportsOptions::Enabled,
|
||||||
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
CliSys::default(),
|
CliSys::default(),
|
||||||
);
|
);
|
||||||
let unfurler = SpecifierUnfurler::new(
|
let unfurler = SpecifierUnfurler::new(Arc::new(workspace_resolver), true);
|
||||||
Some(Arc::new(CliSloppyImportsResolver::new(
|
|
||||||
SloppyImportsCachedFs::new(CliSys::default()),
|
|
||||||
))),
|
|
||||||
Arc::new(workspace_resolver),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unfurling TS file should apply changes.
|
// Unfurling TS file should apply changes.
|
||||||
{
|
{
|
||||||
|
@ -926,18 +907,14 @@ export type * from "./c.d.ts";
|
||||||
Arc::new(pkg_json_subtract),
|
Arc::new(pkg_json_subtract),
|
||||||
Arc::new(pkg_json_publishing),
|
Arc::new(pkg_json_publishing),
|
||||||
],
|
],
|
||||||
deno_config::workspace::PackageJsonDepResolution::Enabled,
|
deno_resolver::workspace::PackageJsonDepResolution::Enabled,
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
sys.clone(),
|
sys.clone(),
|
||||||
);
|
);
|
||||||
let unfurler = SpecifierUnfurler::new(
|
let unfurler = SpecifierUnfurler::new(Arc::new(workspace_resolver), true);
|
||||||
Some(Arc::new(CliSloppyImportsResolver::new(
|
|
||||||
SloppyImportsCachedFs::new(sys),
|
|
||||||
))),
|
|
||||||
Arc::new(workspace_resolver),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let source_code = r#"import add from "add";
|
let source_code = r#"import add from "add";
|
||||||
|
|
|
@ -33,13 +33,18 @@ deno_path_util.workspace = true
|
||||||
deno_semver.workspace = true
|
deno_semver.workspace = true
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
import_map.workspace = true
|
||||||
|
indexmap.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
node_resolver.workspace = true
|
node_resolver.workspace = true
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
sys_traits.workspace = true
|
sys_traits.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
sys_traits = { workspace = true, features = ["memory", "real", "serde_json"] }
|
||||||
test_util.workspace = true
|
test_util.workspace = true
|
||||||
|
|
|
@ -12,7 +12,6 @@ use deno_cache_dir::HttpCacheRc;
|
||||||
use deno_cache_dir::LocalHttpCache;
|
use deno_cache_dir::LocalHttpCache;
|
||||||
use deno_config::deno_json::NodeModulesDirMode;
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
use deno_config::workspace::FolderConfigs;
|
use deno_config::workspace::FolderConfigs;
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::VendorEnablement;
|
use deno_config::workspace::VendorEnablement;
|
||||||
use deno_config::workspace::WorkspaceDirectory;
|
use deno_config::workspace::WorkspaceDirectory;
|
||||||
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
||||||
|
@ -61,12 +60,13 @@ use crate::npm::NpmResolverCreateOptions;
|
||||||
use crate::npmrc::discover_npmrc_from_workspace;
|
use crate::npmrc::discover_npmrc_from_workspace;
|
||||||
use crate::npmrc::NpmRcDiscoverError;
|
use crate::npmrc::NpmRcDiscoverError;
|
||||||
use crate::npmrc::ResolvedNpmRcRc;
|
use crate::npmrc::ResolvedNpmRcRc;
|
||||||
use crate::sloppy_imports::SloppyImportsCachedFs;
|
|
||||||
use crate::sloppy_imports::SloppyImportsResolver;
|
|
||||||
use crate::sloppy_imports::SloppyImportsResolverRc;
|
|
||||||
use crate::sync::new_rc;
|
use crate::sync::new_rc;
|
||||||
use crate::sync::MaybeSend;
|
use crate::sync::MaybeSend;
|
||||||
use crate::sync::MaybeSync;
|
use crate::sync::MaybeSync;
|
||||||
|
use crate::workspace::FsCacheOptions;
|
||||||
|
use crate::workspace::PackageJsonDepResolution;
|
||||||
|
use crate::workspace::SloppyImportsOptions;
|
||||||
|
use crate::workspace::WorkspaceResolver;
|
||||||
use crate::DefaultDenoResolverRc;
|
use crate::DefaultDenoResolverRc;
|
||||||
use crate::DenoResolver;
|
use crate::DenoResolver;
|
||||||
use crate::DenoResolverOptions;
|
use crate::DenoResolverOptions;
|
||||||
|
@ -133,7 +133,7 @@ pub trait SpecifiedImportMapProvider:
|
||||||
{
|
{
|
||||||
async fn get(
|
async fn get(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<deno_config::workspace::SpecifiedImportMap>, anyhow::Error>;
|
) -> Result<Option<crate::workspace::SpecifiedImportMap>, anyhow::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -560,7 +560,6 @@ impl<TSys: WorkspaceFactorySys> WorkspaceFactory<TSys> {
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ResolverFactoryOptions {
|
pub struct ResolverFactoryOptions {
|
||||||
pub conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
pub conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
||||||
pub no_sloppy_imports_cache: bool,
|
|
||||||
pub npm_system_info: NpmSystemInfo,
|
pub npm_system_info: NpmSystemInfo,
|
||||||
pub node_resolution_cache: Option<node_resolver::NodeResolutionCacheRc>,
|
pub node_resolution_cache: Option<node_resolver::NodeResolutionCacheRc>,
|
||||||
pub package_json_cache: Option<node_resolver::PackageJsonCacheRc>,
|
pub package_json_cache: Option<node_resolver::PackageJsonCacheRc>,
|
||||||
|
@ -593,8 +592,6 @@ pub struct ResolverFactory<TSys: WorkspaceFactorySys> {
|
||||||
npm_resolver: Deferred<NpmResolver<TSys>>,
|
npm_resolver: Deferred<NpmResolver<TSys>>,
|
||||||
npm_resolution: NpmResolutionCellRc,
|
npm_resolution: NpmResolutionCellRc,
|
||||||
pkg_json_resolver: Deferred<PackageJsonResolverRc<TSys>>,
|
pkg_json_resolver: Deferred<PackageJsonResolverRc<TSys>>,
|
||||||
sloppy_imports_resolver:
|
|
||||||
Deferred<Option<SloppyImportsResolverRc<SloppyImportsCachedFs<TSys>>>>,
|
|
||||||
workspace_factory: WorkspaceFactoryRc<TSys>,
|
workspace_factory: WorkspaceFactoryRc<TSys>,
|
||||||
workspace_resolver: async_once_cell::OnceCell<WorkspaceResolverRc<TSys>>,
|
workspace_resolver: async_once_cell::OnceCell<WorkspaceResolverRc<TSys>>,
|
||||||
}
|
}
|
||||||
|
@ -616,7 +613,6 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
npm_resolution: Default::default(),
|
npm_resolution: Default::default(),
|
||||||
npm_resolver: Default::default(),
|
npm_resolver: Default::default(),
|
||||||
pkg_json_resolver: Default::default(),
|
pkg_json_resolver: Default::default(),
|
||||||
sloppy_imports_resolver: Default::default(),
|
|
||||||
workspace_factory,
|
workspace_factory,
|
||||||
workspace_resolver: Default::default(),
|
workspace_resolver: Default::default(),
|
||||||
options,
|
options,
|
||||||
|
@ -646,7 +642,6 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
.workspace_directory()?
|
.workspace_directory()?
|
||||||
.workspace
|
.workspace
|
||||||
.vendor_dir_path(),
|
.vendor_dir_path(),
|
||||||
sloppy_imports_resolver: self.sloppy_imports_resolver()?.cloned(),
|
|
||||||
workspace_resolver: self.workspace_resolver().await?.clone(),
|
workspace_resolver: self.workspace_resolver().await?.clone(),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -770,38 +765,6 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sloppy_imports_resolver(
|
|
||||||
&self,
|
|
||||||
) -> Result<
|
|
||||||
Option<&SloppyImportsResolverRc<SloppyImportsCachedFs<TSys>>>,
|
|
||||||
anyhow::Error,
|
|
||||||
> {
|
|
||||||
self
|
|
||||||
.sloppy_imports_resolver
|
|
||||||
.get_or_try_init(|| {
|
|
||||||
let enabled = self.options.unstable_sloppy_imports
|
|
||||||
|| self
|
|
||||||
.workspace_factory
|
|
||||||
.workspace_directory()?
|
|
||||||
.workspace
|
|
||||||
.has_unstable("sloppy-imports");
|
|
||||||
if enabled {
|
|
||||||
Ok(Some(new_rc(SloppyImportsResolver::new(
|
|
||||||
if self.options.no_sloppy_imports_cache {
|
|
||||||
SloppyImportsCachedFs::new_without_stat_cache(
|
|
||||||
self.workspace_factory.sys.clone(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
SloppyImportsCachedFs::new(self.workspace_factory.sys.clone())
|
|
||||||
},
|
|
||||||
))))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|v| v.as_ref())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn workspace_resolver(
|
pub async fn workspace_resolver(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<&WorkspaceResolverRc<TSys>, anyhow::Error> {
|
) -> Result<&WorkspaceResolverRc<TSys>, anyhow::Error> {
|
||||||
|
@ -815,7 +778,7 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
Some(import_map) => import_map.get().await?,
|
Some(import_map) => import_map.get().await?,
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let options = deno_config::workspace::CreateResolverOptions {
|
let options = crate::workspace::CreateResolverOptions {
|
||||||
pkg_json_dep_resolution: match self
|
pkg_json_dep_resolution: match self
|
||||||
.options
|
.options
|
||||||
.package_json_dep_resolution
|
.package_json_dep_resolution
|
||||||
|
@ -834,9 +797,24 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
specified_import_map,
|
specified_import_map,
|
||||||
|
sloppy_imports_options: if self.options.unstable_sloppy_imports
|
||||||
|
|| self
|
||||||
|
.workspace_factory
|
||||||
|
.workspace_directory()?
|
||||||
|
.workspace
|
||||||
|
.has_unstable("sloppy-imports")
|
||||||
|
{
|
||||||
|
SloppyImportsOptions::Enabled
|
||||||
|
} else {
|
||||||
|
SloppyImportsOptions::Disabled
|
||||||
|
},
|
||||||
|
fs_cache_options: FsCacheOptions::Enabled,
|
||||||
};
|
};
|
||||||
let resolver = workspace
|
let resolver = WorkspaceResolver::from_workspace(
|
||||||
.create_resolver(self.workspace_factory.sys.clone(), options)?;
|
workspace,
|
||||||
|
self.workspace_factory.sys.clone(),
|
||||||
|
options,
|
||||||
|
)?;
|
||||||
if !resolver.diagnostics().is_empty() {
|
if !resolver.diagnostics().is_empty() {
|
||||||
// todo(dsherret): do not log this in this crate... that should be
|
// todo(dsherret): do not log this in this crate... that should be
|
||||||
// a CLI responsibility
|
// a CLI responsibility
|
||||||
|
|
|
@ -7,11 +7,6 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use boxed_error::Boxed;
|
use boxed_error::Boxed;
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_config::workspace::MappedResolutionDiagnostic;
|
|
||||||
use deno_config::workspace::MappedResolutionError;
|
|
||||||
use deno_config::workspace::WorkspaceResolvePkgJsonFolderError;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_error::JsError;
|
use deno_error::JsError;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_package_json::PackageJsonDepValueParseError;
|
use deno_package_json::PackageJsonDepValueParseError;
|
||||||
|
@ -31,9 +26,6 @@ use npm::NpmReqResolverRc;
|
||||||
use npm::ResolveIfForNpmPackageErrorKind;
|
use npm::ResolveIfForNpmPackageErrorKind;
|
||||||
use npm::ResolvePkgFolderFromDenoReqError;
|
use npm::ResolvePkgFolderFromDenoReqError;
|
||||||
use npm::ResolveReqWithSubPathErrorKind;
|
use npm::ResolveReqWithSubPathErrorKind;
|
||||||
use sloppy_imports::SloppyImportResolverFs;
|
|
||||||
use sloppy_imports::SloppyImportsResolutionKind;
|
|
||||||
use sloppy_imports::SloppyImportsResolverRc;
|
|
||||||
use sys_traits::FsCanonicalize;
|
use sys_traits::FsCanonicalize;
|
||||||
use sys_traits::FsMetadata;
|
use sys_traits::FsMetadata;
|
||||||
use sys_traits::FsRead;
|
use sys_traits::FsRead;
|
||||||
|
@ -41,12 +33,18 @@ use sys_traits::FsReadDir;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::workspace::MappedResolution;
|
||||||
|
use crate::workspace::MappedResolutionDiagnostic;
|
||||||
|
use crate::workspace::MappedResolutionError;
|
||||||
|
use crate::workspace::WorkspaceResolvePkgJsonFolderError;
|
||||||
|
use crate::workspace::WorkspaceResolver;
|
||||||
|
|
||||||
pub mod cjs;
|
pub mod cjs;
|
||||||
pub mod factory;
|
pub mod factory;
|
||||||
pub mod npm;
|
pub mod npm;
|
||||||
pub mod npmrc;
|
pub mod npmrc;
|
||||||
pub mod sloppy_imports;
|
|
||||||
mod sync;
|
mod sync;
|
||||||
|
pub mod workspace;
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
pub type WorkspaceResolverRc<TSys> =
|
pub type WorkspaceResolverRc<TSys> =
|
||||||
|
@ -128,7 +126,6 @@ pub struct DenoResolverOptions<
|
||||||
TInNpmPackageChecker: InNpmPackageChecker,
|
TInNpmPackageChecker: InNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
|
||||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||||
> {
|
> {
|
||||||
pub in_npm_pkg_checker: TInNpmPackageChecker,
|
pub in_npm_pkg_checker: TInNpmPackageChecker,
|
||||||
|
@ -140,8 +137,6 @@ pub struct DenoResolverOptions<
|
||||||
TSys,
|
TSys,
|
||||||
>,
|
>,
|
||||||
>,
|
>,
|
||||||
pub sloppy_imports_resolver:
|
|
||||||
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
|
|
||||||
pub workspace_resolver: WorkspaceResolverRc<TSys>,
|
pub workspace_resolver: WorkspaceResolverRc<TSys>,
|
||||||
/// Whether "bring your own node_modules" is enabled where Deno does not
|
/// Whether "bring your own node_modules" is enabled where Deno does not
|
||||||
/// setup the node_modules directories automatically, but instead uses
|
/// setup the node_modules directories automatically, but instead uses
|
||||||
|
@ -155,14 +150,12 @@ pub type DenoResolverRc<
|
||||||
TInNpmPackageChecker,
|
TInNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver,
|
TNpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs,
|
|
||||||
TSys,
|
TSys,
|
||||||
> = crate::sync::MaybeArc<
|
> = crate::sync::MaybeArc<
|
||||||
DenoResolver<
|
DenoResolver<
|
||||||
TInNpmPackageChecker,
|
TInNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver,
|
TNpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs,
|
|
||||||
TSys,
|
TSys,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
|
@ -173,7 +166,6 @@ pub type DefaultDenoResolverRc<TSys> = DenoResolverRc<
|
||||||
npm::DenoInNpmPackageChecker,
|
npm::DenoInNpmPackageChecker,
|
||||||
node_resolver::DenoIsBuiltInNodeModuleChecker,
|
node_resolver::DenoIsBuiltInNodeModuleChecker,
|
||||||
npm::NpmResolver<TSys>,
|
npm::NpmResolver<TSys>,
|
||||||
sloppy_imports::SloppyImportsCachedFs<TSys>,
|
|
||||||
TSys,
|
TSys,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
@ -184,7 +176,6 @@ pub struct DenoResolver<
|
||||||
TInNpmPackageChecker: InNpmPackageChecker,
|
TInNpmPackageChecker: InNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
|
||||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||||
> {
|
> {
|
||||||
in_npm_pkg_checker: TInNpmPackageChecker,
|
in_npm_pkg_checker: TInNpmPackageChecker,
|
||||||
|
@ -196,8 +187,6 @@ pub struct DenoResolver<
|
||||||
TSys,
|
TSys,
|
||||||
>,
|
>,
|
||||||
>,
|
>,
|
||||||
sloppy_imports_resolver:
|
|
||||||
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
|
|
||||||
workspace_resolver: WorkspaceResolverRc<TSys>,
|
workspace_resolver: WorkspaceResolverRc<TSys>,
|
||||||
is_byonm: bool,
|
is_byonm: bool,
|
||||||
maybe_vendor_specifier: Option<Url>,
|
maybe_vendor_specifier: Option<Url>,
|
||||||
|
@ -207,14 +196,12 @@ impl<
|
||||||
TInNpmPackageChecker: InNpmPackageChecker,
|
TInNpmPackageChecker: InNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
|
||||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||||
>
|
>
|
||||||
DenoResolver<
|
DenoResolver<
|
||||||
TInNpmPackageChecker,
|
TInNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver,
|
TNpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs,
|
|
||||||
TSys,
|
TSys,
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
@ -223,14 +210,12 @@ impl<
|
||||||
TInNpmPackageChecker,
|
TInNpmPackageChecker,
|
||||||
TIsBuiltInNodeModuleChecker,
|
TIsBuiltInNodeModuleChecker,
|
||||||
TNpmPackageFolderResolver,
|
TNpmPackageFolderResolver,
|
||||||
TSloppyImportResolverFs,
|
|
||||||
TSys,
|
TSys,
|
||||||
>,
|
>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
in_npm_pkg_checker: options.in_npm_pkg_checker,
|
in_npm_pkg_checker: options.in_npm_pkg_checker,
|
||||||
node_and_npm_resolver: options.node_and_req_resolver,
|
node_and_npm_resolver: options.node_and_req_resolver,
|
||||||
sloppy_imports_resolver: options.sloppy_imports_resolver,
|
|
||||||
workspace_resolver: options.workspace_resolver,
|
workspace_resolver: options.workspace_resolver,
|
||||||
is_byonm: options.is_byonm,
|
is_byonm: options.is_byonm,
|
||||||
maybe_vendor_specifier: options
|
maybe_vendor_specifier: options
|
||||||
|
@ -277,33 +262,10 @@ impl<
|
||||||
MappedResolution::Normal {
|
MappedResolution::Normal {
|
||||||
specifier,
|
specifier,
|
||||||
maybe_diagnostic: current_diagnostic,
|
maybe_diagnostic: current_diagnostic,
|
||||||
}
|
..
|
||||||
| MappedResolution::ImportMap {
|
|
||||||
specifier,
|
|
||||||
maybe_diagnostic: current_diagnostic,
|
|
||||||
} => {
|
} => {
|
||||||
maybe_diagnostic = current_diagnostic;
|
maybe_diagnostic = current_diagnostic;
|
||||||
// do sloppy imports resolution if enabled
|
Ok(specifier)
|
||||||
if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
|
|
||||||
Ok(
|
|
||||||
sloppy_imports_resolver
|
|
||||||
.resolve(
|
|
||||||
&specifier,
|
|
||||||
match resolution_kind {
|
|
||||||
NodeResolutionKind::Execution => {
|
|
||||||
SloppyImportsResolutionKind::Execution
|
|
||||||
}
|
|
||||||
NodeResolutionKind::Types => {
|
|
||||||
SloppyImportsResolutionKind::Types
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.map(|s| s.into_specifier())
|
|
||||||
.unwrap_or(specifier),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(specifier)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
MappedResolution::WorkspaceJsrPackage { specifier, .. } => {
|
MappedResolution::WorkspaceJsrPackage { specifier, .. } => {
|
||||||
Ok(specifier)
|
Ok(specifier)
|
||||||
|
|
|
@ -1,582 +0,0 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use deno_media_type::MediaType;
|
|
||||||
use deno_path_util::url_from_file_path;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use sys_traits::FsMetadata;
|
|
||||||
use sys_traits::FsMetadataValue;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::sync::MaybeDashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum SloppyImportsFsEntry {
|
|
||||||
File,
|
|
||||||
Dir,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub enum SloppyImportsResolution {
|
|
||||||
/// Ex. `./file.js` to `./file.ts`
|
|
||||||
JsToTs(Url),
|
|
||||||
/// Ex. `./file` to `./file.ts`
|
|
||||||
NoExtension(Url),
|
|
||||||
/// Ex. `./dir` to `./dir/index.ts`
|
|
||||||
Directory(Url),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SloppyImportsResolution {
|
|
||||||
pub fn as_specifier(&self) -> &Url {
|
|
||||||
match self {
|
|
||||||
Self::JsToTs(specifier) => specifier,
|
|
||||||
Self::NoExtension(specifier) => specifier,
|
|
||||||
Self::Directory(specifier) => specifier,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_specifier(self) -> Url {
|
|
||||||
match self {
|
|
||||||
Self::JsToTs(specifier) => specifier,
|
|
||||||
Self::NoExtension(specifier) => specifier,
|
|
||||||
Self::Directory(specifier) => specifier,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_suggestion_message(&self) -> String {
|
|
||||||
format!("Maybe {}", self.as_base_message())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_quick_fix_message(&self) -> String {
|
|
||||||
let message = self.as_base_message();
|
|
||||||
let mut chars = message.chars();
|
|
||||||
format!(
|
|
||||||
"{}{}.",
|
|
||||||
chars.next().unwrap().to_uppercase(),
|
|
||||||
chars.as_str()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_base_message(&self) -> String {
|
|
||||||
match self {
|
|
||||||
SloppyImportsResolution::JsToTs(specifier) => {
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
|
||||||
format!("change the extension to '{}'", media_type.as_ts_extension())
|
|
||||||
}
|
|
||||||
SloppyImportsResolution::NoExtension(specifier) => {
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
|
||||||
format!("add a '{}' extension", media_type.as_ts_extension())
|
|
||||||
}
|
|
||||||
SloppyImportsResolution::Directory(specifier) => {
|
|
||||||
let file_name = specifier
|
|
||||||
.path()
|
|
||||||
.rsplit_once('/')
|
|
||||||
.map(|(_, file_name)| file_name)
|
|
||||||
.unwrap_or(specifier.path());
|
|
||||||
format!("specify path to '{}' file in directory instead", file_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The kind of resolution currently being done.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum SloppyImportsResolutionKind {
|
|
||||||
/// Resolving for code that will be executed.
|
|
||||||
Execution,
|
|
||||||
/// Resolving for code that will be used for type information.
|
|
||||||
Types,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SloppyImportsResolutionKind {
|
|
||||||
pub fn is_types(&self) -> bool {
|
|
||||||
*self == SloppyImportsResolutionKind::Types
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SloppyImportsResolutionKind>
|
|
||||||
for deno_config::workspace::ResolutionKind
|
|
||||||
{
|
|
||||||
fn from(value: SloppyImportsResolutionKind) -> Self {
|
|
||||||
match value {
|
|
||||||
SloppyImportsResolutionKind::Execution => Self::Execution,
|
|
||||||
SloppyImportsResolutionKind::Types => Self::Types,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait SloppyImportResolverFs {
|
|
||||||
fn stat_sync(&self, path: &Path) -> Option<SloppyImportsFsEntry>;
|
|
||||||
|
|
||||||
fn is_file(&self, path: &Path) -> bool {
|
|
||||||
self.stat_sync(path) == Some(SloppyImportsFsEntry::File)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
|
||||||
pub type SloppyImportsResolverRc<TSloppyImportResolverFs> =
|
|
||||||
crate::sync::MaybeArc<SloppyImportsResolver<TSloppyImportResolverFs>>;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SloppyImportsResolver<Fs: SloppyImportResolverFs> {
|
|
||||||
fs: Fs,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Fs: SloppyImportResolverFs> SloppyImportsResolver<Fs> {
|
|
||||||
pub fn new(fs: Fs) -> Self {
|
|
||||||
Self { fs }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(
|
|
||||||
&self,
|
|
||||||
specifier: &Url,
|
|
||||||
resolution_kind: SloppyImportsResolutionKind,
|
|
||||||
) -> Option<SloppyImportsResolution> {
|
|
||||||
fn path_without_ext(
|
|
||||||
path: &Path,
|
|
||||||
media_type: MediaType,
|
|
||||||
) -> Option<Cow<str>> {
|
|
||||||
let old_path_str = path.to_string_lossy();
|
|
||||||
match media_type {
|
|
||||||
MediaType::Unknown => Some(old_path_str),
|
|
||||||
_ => old_path_str
|
|
||||||
.strip_suffix(media_type.as_ts_extension())
|
|
||||||
.map(|s| Cow::Owned(s.to_string())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn media_types_to_paths(
|
|
||||||
path_no_ext: &str,
|
|
||||||
original_media_type: MediaType,
|
|
||||||
probe_media_type_types: Vec<MediaType>,
|
|
||||||
reason: SloppyImportsResolutionReason,
|
|
||||||
) -> Vec<(PathBuf, SloppyImportsResolutionReason)> {
|
|
||||||
probe_media_type_types
|
|
||||||
.into_iter()
|
|
||||||
.filter(|media_type| *media_type != original_media_type)
|
|
||||||
.map(|media_type| {
|
|
||||||
(
|
|
||||||
PathBuf::from(format!(
|
|
||||||
"{}{}",
|
|
||||||
path_no_ext,
|
|
||||||
media_type.as_ts_extension()
|
|
||||||
)),
|
|
||||||
reason,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
if specifier.scheme() != "file" {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = url_to_file_path(specifier).ok()?;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
enum SloppyImportsResolutionReason {
|
|
||||||
JsToTs,
|
|
||||||
NoExtension,
|
|
||||||
Directory,
|
|
||||||
}
|
|
||||||
|
|
||||||
let probe_paths: Vec<(PathBuf, SloppyImportsResolutionReason)> =
|
|
||||||
match self.fs.stat_sync(&path) {
|
|
||||||
Some(SloppyImportsFsEntry::File) => {
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
|
||||||
// attempt to resolve the .d.ts file before the .js file
|
|
||||||
let probe_media_type_types = match media_type {
|
|
||||||
MediaType::JavaScript => {
|
|
||||||
vec![(MediaType::Dts), MediaType::JavaScript]
|
|
||||||
}
|
|
||||||
MediaType::Mjs => {
|
|
||||||
vec![MediaType::Dmts, MediaType::Dts, MediaType::Mjs]
|
|
||||||
}
|
|
||||||
MediaType::Cjs => {
|
|
||||||
vec![MediaType::Dcts, MediaType::Dts, MediaType::Cjs]
|
|
||||||
}
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
let path_no_ext = path_without_ext(&path, media_type)?;
|
|
||||||
media_types_to_paths(
|
|
||||||
&path_no_ext,
|
|
||||||
media_type,
|
|
||||||
probe_media_type_types,
|
|
||||||
SloppyImportsResolutionReason::JsToTs,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry @ None | entry @ Some(SloppyImportsFsEntry::Dir) => {
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
|
||||||
let probe_media_type_types = match media_type {
|
|
||||||
MediaType::JavaScript => (
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
vec![MediaType::TypeScript, MediaType::Tsx, MediaType::Dts]
|
|
||||||
} else {
|
|
||||||
vec![MediaType::TypeScript, MediaType::Tsx]
|
|
||||||
},
|
|
||||||
SloppyImportsResolutionReason::JsToTs,
|
|
||||||
),
|
|
||||||
MediaType::Jsx => {
|
|
||||||
(vec![MediaType::Tsx], SloppyImportsResolutionReason::JsToTs)
|
|
||||||
}
|
|
||||||
MediaType::Mjs => (
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
vec![MediaType::Mts, MediaType::Dmts, MediaType::Dts]
|
|
||||||
} else {
|
|
||||||
vec![MediaType::Mts]
|
|
||||||
},
|
|
||||||
SloppyImportsResolutionReason::JsToTs,
|
|
||||||
),
|
|
||||||
MediaType::Cjs => (
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
vec![MediaType::Cts, MediaType::Dcts, MediaType::Dts]
|
|
||||||
} else {
|
|
||||||
vec![MediaType::Cts]
|
|
||||||
},
|
|
||||||
SloppyImportsResolutionReason::JsToTs,
|
|
||||||
),
|
|
||||||
MediaType::TypeScript
|
|
||||||
| MediaType::Mts
|
|
||||||
| MediaType::Cts
|
|
||||||
| MediaType::Dts
|
|
||||||
| MediaType::Dmts
|
|
||||||
| MediaType::Dcts
|
|
||||||
| MediaType::Tsx
|
|
||||||
| MediaType::Json
|
|
||||||
| MediaType::Wasm
|
|
||||||
| MediaType::Css
|
|
||||||
| MediaType::SourceMap => {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
MediaType::Unknown => (
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
vec![
|
|
||||||
MediaType::TypeScript,
|
|
||||||
MediaType::Tsx,
|
|
||||||
MediaType::Mts,
|
|
||||||
MediaType::Dts,
|
|
||||||
MediaType::Dmts,
|
|
||||||
MediaType::Dcts,
|
|
||||||
MediaType::JavaScript,
|
|
||||||
MediaType::Jsx,
|
|
||||||
MediaType::Mjs,
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
vec![
|
|
||||||
MediaType::TypeScript,
|
|
||||||
MediaType::JavaScript,
|
|
||||||
MediaType::Tsx,
|
|
||||||
MediaType::Jsx,
|
|
||||||
MediaType::Mts,
|
|
||||||
MediaType::Mjs,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
SloppyImportsResolutionReason::NoExtension,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let mut probe_paths = match path_without_ext(&path, media_type) {
|
|
||||||
Some(path_no_ext) => media_types_to_paths(
|
|
||||||
&path_no_ext,
|
|
||||||
media_type,
|
|
||||||
probe_media_type_types.0,
|
|
||||||
probe_media_type_types.1,
|
|
||||||
),
|
|
||||||
None => vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
if matches!(entry, Some(SloppyImportsFsEntry::Dir)) {
|
|
||||||
// try to resolve at the index file
|
|
||||||
if resolution_kind.is_types() {
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.ts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.mts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.d.ts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.d.mts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.js"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.mjs"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.tsx"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.jsx"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.ts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.mts"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.tsx"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.js"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.mjs"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
probe_paths.push((
|
|
||||||
path.join("index.jsx"),
|
|
||||||
SloppyImportsResolutionReason::Directory,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if probe_paths.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
probe_paths
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (probe_path, reason) in probe_paths {
|
|
||||||
if self.fs.is_file(&probe_path) {
|
|
||||||
if let Ok(specifier) = url_from_file_path(&probe_path) {
|
|
||||||
match reason {
|
|
||||||
SloppyImportsResolutionReason::JsToTs => {
|
|
||||||
return Some(SloppyImportsResolution::JsToTs(specifier));
|
|
||||||
}
|
|
||||||
SloppyImportsResolutionReason::NoExtension => {
|
|
||||||
return Some(SloppyImportsResolution::NoExtension(specifier));
|
|
||||||
}
|
|
||||||
SloppyImportsResolutionReason::Directory => {
|
|
||||||
return Some(SloppyImportsResolution::Directory(specifier));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SloppyImportsCachedFs<TSys: FsMetadata> {
|
|
||||||
sys: TSys,
|
|
||||||
cache: Option<MaybeDashMap<PathBuf, Option<SloppyImportsFsEntry>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<TSys: FsMetadata> SloppyImportsCachedFs<TSys> {
|
|
||||||
pub fn new(sys: TSys) -> Self {
|
|
||||||
Self {
|
|
||||||
sys,
|
|
||||||
cache: Some(Default::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_without_stat_cache(sys: TSys) -> Self {
|
|
||||||
Self { sys, cache: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<TSys: FsMetadata> SloppyImportResolverFs for SloppyImportsCachedFs<TSys> {
|
|
||||||
fn stat_sync(&self, path: &Path) -> Option<SloppyImportsFsEntry> {
|
|
||||||
if let Some(cache) = &self.cache {
|
|
||||||
if let Some(entry) = cache.get(path) {
|
|
||||||
return *entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let entry = self.sys.fs_metadata(path).ok().and_then(|stat| {
|
|
||||||
if stat.file_type().is_file() {
|
|
||||||
Some(SloppyImportsFsEntry::File)
|
|
||||||
} else if stat.file_type().is_dir() {
|
|
||||||
Some(SloppyImportsFsEntry::Dir)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(cache) = &self.cache {
|
|
||||||
cache.insert(path.to_owned(), entry);
|
|
||||||
}
|
|
||||||
entry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use test_util::TestContext;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_unstable_sloppy_imports() {
|
|
||||||
fn resolve(specifier: &Url) -> Option<SloppyImportsResolution> {
|
|
||||||
resolve_with_resolution_kind(
|
|
||||||
specifier,
|
|
||||||
SloppyImportsResolutionKind::Execution,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_types(specifier: &Url) -> Option<SloppyImportsResolution> {
|
|
||||||
resolve_with_resolution_kind(
|
|
||||||
specifier,
|
|
||||||
SloppyImportsResolutionKind::Types,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_with_resolution_kind(
|
|
||||||
specifier: &Url,
|
|
||||||
resolution_kind: SloppyImportsResolutionKind,
|
|
||||||
) -> Option<SloppyImportsResolution> {
|
|
||||||
struct RealSloppyImportsResolverFs;
|
|
||||||
impl SloppyImportResolverFs for RealSloppyImportsResolverFs {
|
|
||||||
fn stat_sync(&self, path: &Path) -> Option<SloppyImportsFsEntry> {
|
|
||||||
#[allow(clippy::disallowed_methods)]
|
|
||||||
let stat = std::fs::metadata(path).ok()?;
|
|
||||||
if stat.is_dir() {
|
|
||||||
Some(SloppyImportsFsEntry::Dir)
|
|
||||||
} else if stat.is_file() {
|
|
||||||
Some(SloppyImportsFsEntry::File)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SloppyImportsResolver::new(RealSloppyImportsResolverFs)
|
|
||||||
.resolve(specifier, resolution_kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = TestContext::default();
|
|
||||||
let temp_dir = context.temp_dir().path();
|
|
||||||
|
|
||||||
// scenarios like resolving ./example.js to ./example.ts
|
|
||||||
for (ext_from, ext_to) in [("js", "ts"), ("js", "tsx"), ("mjs", "mts")] {
|
|
||||||
let ts_file = temp_dir.join(format!("file.{}", ext_to));
|
|
||||||
ts_file.write("");
|
|
||||||
assert_eq!(resolve(&ts_file.url_file()), None);
|
|
||||||
assert_eq!(
|
|
||||||
resolve(
|
|
||||||
&temp_dir
|
|
||||||
.url_dir()
|
|
||||||
.join(&format!("file.{}", ext_from))
|
|
||||||
.unwrap()
|
|
||||||
),
|
|
||||||
Some(SloppyImportsResolution::JsToTs(ts_file.url_file())),
|
|
||||||
);
|
|
||||||
ts_file.remove_file();
|
|
||||||
}
|
|
||||||
|
|
||||||
// no extension scenarios
|
|
||||||
for ext in ["js", "ts", "js", "tsx", "jsx", "mjs", "mts"] {
|
|
||||||
let file = temp_dir.join(format!("file.{}", ext));
|
|
||||||
file.write("");
|
|
||||||
assert_eq!(
|
|
||||||
resolve(
|
|
||||||
&temp_dir
|
|
||||||
.url_dir()
|
|
||||||
.join("file") // no ext
|
|
||||||
.unwrap()
|
|
||||||
),
|
|
||||||
Some(SloppyImportsResolution::NoExtension(file.url_file()))
|
|
||||||
);
|
|
||||||
file.remove_file();
|
|
||||||
}
|
|
||||||
|
|
||||||
// .ts and .js exists, .js specified (goes to specified)
|
|
||||||
{
|
|
||||||
let ts_file = temp_dir.join("file.ts");
|
|
||||||
ts_file.write("");
|
|
||||||
let js_file = temp_dir.join("file.js");
|
|
||||||
js_file.write("");
|
|
||||||
assert_eq!(resolve(&js_file.url_file()), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only js exists, .js specified
|
|
||||||
{
|
|
||||||
let js_only_file = temp_dir.join("js_only.js");
|
|
||||||
js_only_file.write("");
|
|
||||||
assert_eq!(resolve(&js_only_file.url_file()), None);
|
|
||||||
assert_eq!(resolve_types(&js_only_file.url_file()), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolving a directory to an index file
|
|
||||||
{
|
|
||||||
let routes_dir = temp_dir.join("routes");
|
|
||||||
routes_dir.create_dir_all();
|
|
||||||
let index_file = routes_dir.join("index.ts");
|
|
||||||
index_file.write("");
|
|
||||||
assert_eq!(
|
|
||||||
resolve(&routes_dir.url_file()),
|
|
||||||
Some(SloppyImportsResolution::Directory(index_file.url_file())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// both a directory and a file with specifier is present
|
|
||||||
{
|
|
||||||
let api_dir = temp_dir.join("api");
|
|
||||||
api_dir.create_dir_all();
|
|
||||||
let bar_file = api_dir.join("bar.ts");
|
|
||||||
bar_file.write("");
|
|
||||||
let api_file = temp_dir.join("api.ts");
|
|
||||||
api_file.write("");
|
|
||||||
assert_eq!(
|
|
||||||
resolve(&api_dir.url_file()),
|
|
||||||
Some(SloppyImportsResolution::NoExtension(api_file.url_file())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_sloppy_import_resolution_suggestion_message() {
|
|
||||||
// directory
|
|
||||||
assert_eq!(
|
|
||||||
SloppyImportsResolution::Directory(
|
|
||||||
Url::parse("file:///dir/index.js").unwrap()
|
|
||||||
)
|
|
||||||
.as_suggestion_message(),
|
|
||||||
"Maybe specify path to 'index.js' file in directory instead"
|
|
||||||
);
|
|
||||||
// no ext
|
|
||||||
assert_eq!(
|
|
||||||
SloppyImportsResolution::NoExtension(
|
|
||||||
Url::parse("file:///dir/index.mjs").unwrap()
|
|
||||||
)
|
|
||||||
.as_suggestion_message(),
|
|
||||||
"Maybe add a '.mjs' extension"
|
|
||||||
);
|
|
||||||
// js to ts
|
|
||||||
assert_eq!(
|
|
||||||
SloppyImportsResolution::JsToTs(
|
|
||||||
Url::parse("file:///dir/index.mts").unwrap()
|
|
||||||
)
|
|
||||||
.as_suggestion_message(),
|
|
||||||
"Maybe change the extension to '.mts'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
2812
resolvers/deno/workspace.rs
Normal file
2812
resolvers/deno/workspace.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -110,15 +110,6 @@ pub enum NodeResolutionKind {
|
||||||
Types,
|
Types,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NodeResolutionKind> for deno_config::workspace::ResolutionKind {
|
|
||||||
fn from(value: NodeResolutionKind) -> Self {
|
|
||||||
match value {
|
|
||||||
NodeResolutionKind::Execution => Self::Execution,
|
|
||||||
NodeResolutionKind::Types => Self::Types,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeResolutionKind {
|
impl NodeResolutionKind {
|
||||||
pub fn is_types(&self) -> bool {
|
pub fn is_types(&self) -> bool {
|
||||||
matches!(self, NodeResolutionKind::Types)
|
matches!(self, NodeResolutionKind::Types)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "check --quiet subdir/mod.ts",
|
||||||
|
"output": ""
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDirs": ["subdir", "subdir_types"]
|
||||||
|
},
|
||||||
|
"unstable": ["sloppy-imports"]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { someType } from "./import";
|
||||||
|
const foo: someType = "";
|
||||||
|
console.log(foo);
|
|
@ -0,0 +1 @@
|
||||||
|
export type someType = string;
|
Loading…
Add table
Add a link
Reference in a new issue