mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 10:59:13 +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]]
|
||||
name = "deno_config"
|
||||
version = "0.47.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f7883c48549bab8e446a58c64ee3d106a13052d2ff5e864de765a60260cb02b"
|
||||
checksum = "6c486df63f7fa0f2142c7eba286c7be87a3cd8c93f66f744fb5853a77cf4347b"
|
||||
dependencies = [
|
||||
"boxed_error",
|
||||
"capacity_builder 0.5.0",
|
||||
|
@ -2382,10 +2382,14 @@ dependencies = [
|
|||
"deno_semver",
|
||||
"deno_terminal 0.2.0",
|
||||
"futures",
|
||||
"import_map",
|
||||
"indexmap 2.3.0",
|
||||
"log",
|
||||
"node_resolver",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sys_traits",
|
||||
"test_server",
|
||||
"thiserror 2.0.3",
|
||||
|
@ -8033,6 +8037,8 @@ dependencies = [
|
|||
"getrandom",
|
||||
"libc",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
|||
deno_core = { version = "0.333.0" }
|
||||
|
||||
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_media_type = { version = "=0.2.5", features = ["module_specifier"] }
|
||||
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-util = { version = "0.1.10", features = ["tokio", "client", "client-legacy", "server", "server-auto"] }
|
||||
hyper_v014 = { package = "hyper", version = "0.14.26", features = ["runtime", "http1"] }
|
||||
import_map = { version = "0.21.0", features = ["ext"] }
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
ipnet = "2.3"
|
||||
jsonc-parser = { version = "=0.26.2", features = ["serde"] }
|
||||
|
|
|
@ -9,7 +9,6 @@ use std::sync::Arc;
|
|||
use deno_cache_dir::npm::NpmCacheDir;
|
||||
use deno_config::workspace::Workspace;
|
||||
use deno_config::workspace::WorkspaceDirectory;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
|
@ -38,6 +37,7 @@ use deno_resolver::factory::ResolverFactoryOptions;
|
|||
use deno_resolver::factory::SpecifiedImportMapProvider;
|
||||
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_fs::RealFs;
|
||||
use deno_runtime::deno_permissions::Permissions;
|
||||
|
@ -97,7 +97,6 @@ use crate::resolver::CliDenoResolver;
|
|||
use crate::resolver::CliNpmGraphResolver;
|
||||
use crate::resolver::CliNpmReqResolver;
|
||||
use crate::resolver::CliResolver;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::resolver::FoundPackageJsonDepFlag;
|
||||
use crate::standalone::binary::DenoCompileBinaryWriter;
|
||||
use crate::sys::CliSys;
|
||||
|
@ -160,7 +159,8 @@ struct CliSpecifiedImportMapProvider {
|
|||
impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
||||
async fn get(
|
||||
&self,
|
||||
) -> Result<Option<deno_config::workspace::SpecifiedImportMap>, AnyError> {
|
||||
) -> Result<Option<deno_resolver::workspace::SpecifiedImportMap>, AnyError>
|
||||
{
|
||||
async fn resolve_import_map_value_from_specifier(
|
||||
specifier: &Url,
|
||||
file_fetcher: &CliFileFetcher,
|
||||
|
@ -189,7 +189,7 @@ impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
|||
.with_context(|| {
|
||||
format!("Unable to load '{}' import map", specifier)
|
||||
})?;
|
||||
Ok(Some(deno_config::workspace::SpecifiedImportMap {
|
||||
Ok(Some(deno_resolver::workspace::SpecifiedImportMap {
|
||||
base_url: specifier,
|
||||
value,
|
||||
}))
|
||||
|
@ -199,7 +199,7 @@ impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
|
|||
self.workspace_external_import_map_loader.get_or_load()?
|
||||
{
|
||||
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,
|
||||
value: import_map.value.clone(),
|
||||
}))
|
||||
|
@ -646,7 +646,6 @@ impl CliFactory {
|
|||
ResolverFactoryOptions {
|
||||
conditions_from_resolution_mode: Default::default(),
|
||||
node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)),
|
||||
no_sloppy_imports_cache: false,
|
||||
npm_system_info: self.flags.subcommand.npm_system_info(),
|
||||
specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider {
|
||||
cli_options: self.cli_options()?.clone(),
|
||||
|
@ -663,7 +662,7 @@ impl CliFactory {
|
|||
DenoSubcommand::Publish(_) => {
|
||||
// the node_modules directory is not published to jsr, so resolve
|
||||
// dependencies via the package.json rather than using node resolution
|
||||
Some(deno_config::workspace::PackageJsonDepResolution::Enabled)
|
||||
Some(deno_resolver::workspace::PackageJsonDepResolution::Enabled)
|
||||
}
|
||||
_ => 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> {
|
||||
Ok(&self.workspace_directory()?.workspace)
|
||||
}
|
||||
|
@ -790,10 +783,9 @@ impl CliFactory {
|
|||
}
|
||||
|
||||
pub async fn lint_rule_provider(&self) -> Result<LintRuleProvider, AnyError> {
|
||||
Ok(LintRuleProvider::new(
|
||||
self.sloppy_imports_resolver()?.cloned(),
|
||||
Some(self.workspace_resolver().await?.clone()),
|
||||
))
|
||||
Ok(LintRuleProvider::new(Some(
|
||||
self.workspace_resolver().await?.clone(),
|
||||
)))
|
||||
}
|
||||
|
||||
pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> {
|
||||
|
|
|
@ -34,8 +34,7 @@ use deno_graph::SpecifierError;
|
|||
use deno_graph::WorkspaceFastCheckOption;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||
use deno_resolver::workspace::sloppy_imports_resolve;
|
||||
use deno_runtime::deno_node;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_semver::jsr::JsrDepPackageReq;
|
||||
|
@ -62,7 +61,6 @@ use crate::npm::CliNpmResolver;
|
|||
use crate::resolver::CliCjsTracker;
|
||||
use crate::resolver::CliNpmGraphResolver;
|
||||
use crate::resolver::CliResolver;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::check;
|
||||
use crate::tools::check::CheckError;
|
||||
|
@ -949,11 +947,14 @@ pub fn maybe_additional_sloppy_imports_message(
|
|||
sys: &CliSys,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<String> {
|
||||
let (resolved, sloppy_reason) = sloppy_imports_resolve(
|
||||
specifier,
|
||||
deno_resolver::workspace::ResolutionKind::Execution,
|
||||
sys.clone(),
|
||||
)?;
|
||||
Some(format!(
|
||||
"{} {}",
|
||||
CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(sys.clone()))
|
||||
.resolve(specifier, SloppyImportsResolutionKind::Execution)?
|
||||
.as_suggestion_message(),
|
||||
sloppy_reason.suggestion_message_for_specifier(&resolved),
|
||||
RUN_WITH_SLOPPY_IMPORTS_MSG
|
||||
))
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_media_type::MediaType;
|
||||
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
||||
use deno_runtime::deno_telemetry::OtelConfig;
|
||||
use deno_semver::Version;
|
||||
|
|
|
@ -9,7 +9,6 @@ use std::path::Path;
|
|||
use deno_ast::SourceRange;
|
||||
use deno_ast::SourceRangedForSpanned;
|
||||
use deno_ast::SourceTextInfo;
|
||||
use deno_config::workspace::MappedResolution;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::serde::Deserialize;
|
||||
use deno_core::serde::Serialize;
|
||||
|
@ -20,6 +19,7 @@ use deno_error::JsErrorBox;
|
|||
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||
use deno_resolver::workspace::MappedResolution;
|
||||
use deno_runtime::deno_node::PathClean;
|
||||
use deno_semver::jsr::JsrPackageNvReference;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
|
@ -1348,11 +1348,10 @@ impl CodeActionCollection {
|
|||
let npm_ref = if let Ok(resolution) = workspace_resolver.resolve(
|
||||
&dep_key,
|
||||
document.specifier(),
|
||||
deno_config::workspace::ResolutionKind::Execution,
|
||||
deno_resolver::workspace::ResolutionKind::Execution,
|
||||
) {
|
||||
let specifier = match resolution {
|
||||
MappedResolution::Normal { specifier, .. }
|
||||
| MappedResolution::ImportMap { specifier, .. } => specifier,
|
||||
MappedResolution::Normal { specifier, .. } => specifier,
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -21,16 +21,12 @@ use deno_config::deno_json::TsConfig;
|
|||
use deno_config::deno_json::TsConfigWithIgnoredOptions;
|
||||
use deno_config::glob::FilePatterns;
|
||||
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::Workspace;
|
||||
use deno_config::workspace::WorkspaceCache;
|
||||
use deno_config::workspace::WorkspaceDirectory;
|
||||
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
||||
use deno_config::workspace::WorkspaceDiscoverOptions;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
|
@ -49,7 +45,12 @@ use deno_npm::npm_rc::ResolvedNpmRc;
|
|||
use deno_package_json::PackageJsonCache;
|
||||
use deno_path_util::url_to_file_path;
|
||||
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 indexmap::IndexSet;
|
||||
use lsp_types::ClientCapabilities;
|
||||
|
@ -65,7 +66,6 @@ use crate::args::LintFlags;
|
|||
use crate::args::LintOptions;
|
||||
use crate::file_fetcher::CliFileFetcher;
|
||||
use crate::lsp::logging::lsp_warn;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::lint::CliLinter;
|
||||
use crate::tools::lint::CliLinterOptions;
|
||||
|
@ -1206,7 +1206,6 @@ pub struct ConfigData {
|
|||
pub lockfile: Option<Arc<CliLockfile>>,
|
||||
pub npmrc: Option<Arc<ResolvedNpmRc>>,
|
||||
pub resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||
pub sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
pub import_map_from_settings: Option<ModuleSpecifier>,
|
||||
pub unstable: BTreeSet<String>,
|
||||
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
||||
|
@ -1569,35 +1568,52 @@ impl ConfigData {
|
|||
None
|
||||
}
|
||||
};
|
||||
let resolver = member_dir
|
||||
let unstable = member_dir
|
||||
.workspace
|
||||
.create_resolver(
|
||||
CliSys::default(),
|
||||
CreateResolverOptions {
|
||||
pkg_json_dep_resolution,
|
||||
specified_import_map,
|
||||
.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 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() {
|
||||
lsp_warn!(
|
||||
" Resolver diagnostics:\n{}",
|
||||
|
@ -1609,26 +1625,8 @@ impl ConfigData {
|
|||
.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 lint_rule_provider = LintRuleProvider::new(
|
||||
sloppy_imports_resolver.clone(),
|
||||
Some(resolver.clone()),
|
||||
);
|
||||
let lint_rule_provider = LintRuleProvider::new(Some(resolver.clone()));
|
||||
|
||||
let lint_options = LintOptions::resolve(
|
||||
member_dir.dir_path(),
|
||||
|
@ -1676,7 +1674,6 @@ impl ConfigData {
|
|||
canonicalized_scope,
|
||||
member_dir,
|
||||
resolver,
|
||||
sloppy_imports_resolver,
|
||||
fmt_config,
|
||||
lint_config,
|
||||
test_config,
|
||||
|
|
|
@ -27,9 +27,7 @@ use deno_graph::Resolution;
|
|||
use deno_graph::ResolutionError;
|
||||
use deno_graph::SpecifierError;
|
||||
use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||
use deno_resolver::workspace::sloppy_imports_resolve;
|
||||
use deno_runtime::deno_node;
|
||||
use deno_runtime::tokio_util::create_basic_runtime;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
|
@ -64,7 +62,6 @@ use crate::graph_util;
|
|||
use crate::graph_util::enhanced_resolution_error_message;
|
||||
use crate::lsp::logging::lsp_warn;
|
||||
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tools::lint::CliLinter;
|
||||
use crate::tools::lint::CliLinterOptions;
|
||||
|
@ -1013,7 +1010,7 @@ fn generate_lint_diagnostics(
|
|||
Arc::new(LintConfig::new_with_base(PathBuf::from("/"))),
|
||||
Arc::new(CliLinter::new(CliLinterOptions {
|
||||
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)
|
||||
},
|
||||
fix: false,
|
||||
|
@ -1443,14 +1440,14 @@ impl DenoDiagnostic {
|
|||
pub fn to_lsp_diagnostic(&self, range: &lsp::Range) -> lsp::Diagnostic {
|
||||
fn no_local_message(
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_sloppy_resolution: Option<&SloppyImportsResolution>,
|
||||
suggestion_message: Option<String>,
|
||||
) -> String {
|
||||
let mut message = format!(
|
||||
"Unable to load a local module: {}\n",
|
||||
to_percent_decoded_str(specifier.as_ref())
|
||||
);
|
||||
if let Some(res) = maybe_sloppy_resolution {
|
||||
message.push_str(&res.as_suggestion_message());
|
||||
if let Some(suggestion_message) = suggestion_message {
|
||||
message.push_str(&suggestion_message);
|
||||
message.push('.');
|
||||
} else {
|
||||
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::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) => {
|
||||
let maybe_sloppy_resolution = CliSloppyImportsResolver::new(
|
||||
SloppyImportsCachedFs::new(CliSys::default())
|
||||
).resolve(specifier, SloppyImportsResolutionKind::Execution);
|
||||
let data = maybe_sloppy_resolution.as_ref().map(|res| {
|
||||
let sloppy_resolution = sloppy_imports_resolve(specifier, deno_resolver::workspace::ResolutionKind::Execution, CliSys::default());
|
||||
let data = sloppy_resolution.as_ref().map(|(resolved, sloppy_reason)| {
|
||||
json!({
|
||||
"specifier": specifier,
|
||||
"to": res.as_specifier(),
|
||||
"message": res.as_quick_fix_message(),
|
||||
"to": resolved,
|
||||
"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::ResolutionError(err) => {
|
||||
|
|
|
@ -12,8 +12,6 @@ use deno_ast::MediaType;
|
|||
use deno_cache_dir::npm::NpmCacheDir;
|
||||
use deno_cache_dir::HttpCache;
|
||||
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::url::Url;
|
||||
use deno_graph::GraphImport;
|
||||
|
@ -29,6 +27,8 @@ use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
|||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||
use deno_resolver::npm::NpmReqResolverOptions;
|
||||
use deno_resolver::npmrc::create_default_npmrc;
|
||||
use deno_resolver::workspace::PackageJsonDepResolution;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
use deno_resolver::DenoResolverOptions;
|
||||
use deno_resolver::NodeAndNpmReqResolver;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
|
@ -844,9 +844,6 @@ impl<'a> ResolverFactory<'a> {
|
|||
}
|
||||
_ => None,
|
||||
},
|
||||
sloppy_imports_resolver: self
|
||||
.config_data
|
||||
.and_then(|d| d.sloppy_imports_resolver.clone()),
|
||||
workspace_resolver: self
|
||||
.config_data
|
||||
.map(|d| d.resolver.clone())
|
||||
|
@ -860,6 +857,8 @@ impl<'a> ResolverFactory<'a> {
|
|||
PackageJsonDepResolution::Disabled,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
self.sys.clone(),
|
||||
))
|
||||
}),
|
||||
|
|
|
@ -4,8 +4,6 @@ use std::sync::Arc;
|
|||
|
||||
use async_trait::async_trait;
|
||||
use dashmap::DashSet;
|
||||
use deno_config::workspace::MappedResolutionDiagnostic;
|
||||
use deno_config::workspace::MappedResolutionError;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_graph::source::ResolveError;
|
||||
|
@ -14,8 +12,8 @@ use deno_graph::NpmLoadError;
|
|||
use deno_graph::NpmResolvePkgReqsResult;
|
||||
use deno_npm::resolution::NpmResolutionError;
|
||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolver;
|
||||
use deno_resolver::workspace::MappedResolutionDiagnostic;
|
||||
use deno_resolver::workspace::MappedResolutionError;
|
||||
use deno_runtime::colors;
|
||||
use deno_runtime::deno_node::is_builtin_node_module;
|
||||
use deno_semver::package::PackageReq;
|
||||
|
@ -35,14 +33,10 @@ pub type CliCjsTracker =
|
|||
deno_resolver::cjs::CjsTracker<DenoInNpmPackageChecker, CliSys>;
|
||||
pub type CliIsCjsResolver =
|
||||
deno_resolver::cjs::IsCjsResolver<DenoInNpmPackageChecker, CliSys>;
|
||||
pub type CliSloppyImportsCachedFs = SloppyImportsCachedFs<CliSys>;
|
||||
pub type CliSloppyImportsResolver =
|
||||
SloppyImportsResolver<CliSloppyImportsCachedFs>;
|
||||
pub type CliDenoResolver = deno_resolver::DenoResolver<
|
||||
DenoInNpmPackageChecker,
|
||||
DenoIsBuiltInNodeModuleChecker,
|
||||
CliNpmResolver,
|
||||
CliSloppyImportsCachedFs,
|
||||
CliSys,
|
||||
>;
|
||||
pub type CliNpmReqResolver = deno_resolver::npm::NpmReqResolver<
|
||||
|
|
|
@ -7,9 +7,7 @@ use std::sync::Arc;
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use deno_cache_dir::npm::NpmCacheDir;
|
||||
use deno_config::workspace::MappedResolution;
|
||||
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::ModuleLoaderError;
|
||||
use deno_core::futures::future::LocalBoxFuture;
|
||||
|
@ -59,9 +57,9 @@ use deno_resolver::npm::NpmReqResolver;
|
|||
use deno_resolver::npm::NpmReqResolverOptions;
|
||||
use deno_resolver::npm::NpmResolver;
|
||||
use deno_resolver::npm::NpmResolverCreateOptions;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolver;
|
||||
use deno_resolver::workspace::MappedResolution;
|
||||
use deno_resolver::workspace::SloppyImportsOptions;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
use deno_runtime::code_cache::CodeCache;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::create_host_defined_options;
|
||||
|
@ -107,8 +105,6 @@ struct SharedModuleLoaderState {
|
|||
npm_module_loader: Arc<DenoRtNpmModuleLoader>,
|
||||
npm_registry_permission_checker: NpmRegistryReadPermissionChecker<DenoRtSys>,
|
||||
npm_req_resolver: Arc<DenoRtNpmReqResolver>,
|
||||
sloppy_imports_resolver:
|
||||
Option<SloppyImportsResolver<SloppyImportsCachedFs<DenoRtSys>>>,
|
||||
vfs: Arc<FileBackedVfs>,
|
||||
workspace_resolver: WorkspaceResolver<DenoRtSys>,
|
||||
}
|
||||
|
@ -210,7 +206,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
let mapped_resolution = self.shared.workspace_resolver.resolve(
|
||||
raw_specifier,
|
||||
&referrer,
|
||||
deno_config::workspace::ResolutionKind::Execution,
|
||||
deno_resolver::workspace::ResolutionKind::Execution,
|
||||
);
|
||||
|
||||
match mapped_resolution {
|
||||
|
@ -289,8 +285,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
)
|
||||
}
|
||||
},
|
||||
Ok(MappedResolution::Normal { specifier, .. })
|
||||
| Ok(MappedResolution::ImportMap { specifier, .. }) => {
|
||||
Ok(MappedResolution::Normal { specifier, .. }) => {
|
||||
if let Ok(reference) =
|
||||
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(
|
||||
self
|
||||
.shared
|
||||
|
@ -832,10 +815,6 @@ pub async fn run(
|
|||
pkg_json_resolver.clone(),
|
||||
sys.clone(),
|
||||
));
|
||||
let sloppy_imports_resolver =
|
||||
metadata.unstable_config.sloppy_imports.then(|| {
|
||||
SloppyImportsResolver::new(SloppyImportsCachedFs::new(sys.clone()))
|
||||
});
|
||||
let workspace_resolver = {
|
||||
let import_map = match metadata.workspace_resolver.import_map {
|
||||
Some(import_map) => Some(
|
||||
|
@ -883,6 +862,12 @@ pub async fn run(
|
|||
.collect(),
|
||||
pkg_jsons,
|
||||
metadata.workspace_resolver.pkg_json_resolution,
|
||||
if metadata.unstable_config.sloppy_imports {
|
||||
SloppyImportsOptions::Enabled
|
||||
} else {
|
||||
SloppyImportsOptions::Disabled
|
||||
},
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
sys.clone(),
|
||||
|
@ -915,7 +900,6 @@ pub async fn run(
|
|||
)),
|
||||
npm_registry_permission_checker,
|
||||
npm_req_resolver,
|
||||
sloppy_imports_resolver,
|
||||
vfs: vfs.clone(),
|
||||
workspace_resolver,
|
||||
}),
|
||||
|
|
|
@ -16,7 +16,6 @@ use capacity_builder::BytesAppendable;
|
|||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -49,6 +48,7 @@ use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
|||
use deno_npm::NpmSystemInfo;
|
||||
use deno_path_util::url_from_directory_path;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
use indexmap::IndexMap;
|
||||
use node_resolver::analyze::CjsAnalysis;
|
||||
use node_resolver::analyze::CjsCodeAnalyzer;
|
||||
|
|
|
@ -59,21 +59,18 @@ pub async fn info(
|
|||
let maybe_import_specifier = if let Ok(resolved) = resolver.resolve(
|
||||
&specifier,
|
||||
&cwd_url,
|
||||
deno_config::workspace::ResolutionKind::Execution,
|
||||
deno_resolver::workspace::ResolutionKind::Execution,
|
||||
) {
|
||||
match resolved {
|
||||
deno_config::workspace::MappedResolution::Normal {
|
||||
specifier, ..
|
||||
}
|
||||
| deno_config::workspace::MappedResolution::ImportMap {
|
||||
deno_resolver::workspace::MappedResolution::Normal {
|
||||
specifier,
|
||||
..
|
||||
}
|
||||
| deno_config::workspace::MappedResolution::WorkspaceJsrPackage {
|
||||
| deno_resolver::workspace::MappedResolution::WorkspaceJsrPackage {
|
||||
specifier,
|
||||
..
|
||||
} => Some(specifier),
|
||||
deno_config::workspace::MappedResolution::WorkspaceNpmPackage {
|
||||
deno_resolver::workspace::MappedResolution::WorkspaceNpmPackage {
|
||||
target_pkg_json,
|
||||
sub_path,
|
||||
..
|
||||
|
@ -88,7 +85,7 @@ pub async fn info(
|
|||
)?
|
||||
.into_url()?,
|
||||
),
|
||||
deno_config::workspace::MappedResolution::PackageJson {
|
||||
deno_resolver::workspace::MappedResolution::PackageJson {
|
||||
alias,
|
||||
sub_path,
|
||||
dep_result,
|
||||
|
|
|
@ -499,7 +499,7 @@ fn collect_lint_files(
|
|||
|
||||
#[allow(clippy::print_stdout)]
|
||||
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 configured_rules = rule_provider.resolve_lint_rules(
|
||||
LintRulesConfig {
|
||||
|
@ -686,7 +686,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn get_all_rules() -> Vec<String> {
|
||||
let rule_provider = LintRuleProvider::new(None, None);
|
||||
let rule_provider = LintRuleProvider::new(None);
|
||||
let configured_rules =
|
||||
rule_provider.resolve_lint_rules(Default::default(), None);
|
||||
let mut all_rules = configured_rules
|
||||
|
|
|
@ -7,15 +7,14 @@ use std::sync::Arc;
|
|||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::deno_json::ConfigFile;
|
||||
use deno_config::deno_json::LintRulesConfig;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_lint::diagnostic::LintDiagnostic;
|
||||
use deno_lint::rules::LintRule;
|
||||
use deno_lint::tags;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
|
||||
mod no_sloppy_imports;
|
||||
|
@ -141,19 +140,14 @@ impl ConfiguredRules {
|
|||
}
|
||||
|
||||
pub struct LintRuleProvider {
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||
}
|
||||
|
||||
impl LintRuleProvider {
|
||||
pub fn new(
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
sloppy_imports_resolver,
|
||||
workspace_resolver,
|
||||
}
|
||||
Self { workspace_resolver }
|
||||
}
|
||||
|
||||
pub fn resolve_lint_rules_err_empty(
|
||||
|
@ -172,7 +166,6 @@ impl LintRuleProvider {
|
|||
let deno_lint_rules = deno_lint::rules::get_all_rules();
|
||||
let cli_lint_rules = vec![CliLintRule(CliLintRuleKind::Extended(
|
||||
Box::new(no_sloppy_imports::NoSloppyImportsRule::new(
|
||||
self.sloppy_imports_resolver.clone(),
|
||||
self.workspace_resolver.clone(),
|
||||
)),
|
||||
))];
|
||||
|
@ -274,7 +267,7 @@ mod test {
|
|||
include: 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 mut rule_names = rules
|
||||
.rules
|
||||
|
|
|
@ -6,7 +6,6 @@ use std::collections::HashMap;
|
|||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::SourceRange;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_graph::source::ResolutionKind;
|
||||
use deno_graph::source::ResolveError;
|
||||
|
@ -17,31 +16,25 @@ use deno_lint::diagnostic::LintFix;
|
|||
use deno_lint::diagnostic::LintFixChange;
|
||||
use deno_lint::rules::LintRule;
|
||||
use deno_lint::tags;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||
use deno_resolver::workspace::SloppyImportsResolutionReason;
|
||||
use deno_resolver::workspace::WorkspaceResolver;
|
||||
use text_lines::LineAndColumnIndex;
|
||||
|
||||
use super::ExtendedLintRule;
|
||||
use crate::graph_util::CliJsrUrlProvider;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NoSloppyImportsRule {
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
// None for making printing out the lint rules easy
|
||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||
}
|
||||
|
||||
impl NoSloppyImportsRule {
|
||||
pub fn new(
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
workspace_resolver: Option<Arc<WorkspaceResolver<CliSys>>>,
|
||||
) -> Self {
|
||||
NoSloppyImportsRule {
|
||||
sloppy_imports_resolver,
|
||||
workspace_resolver,
|
||||
}
|
||||
NoSloppyImportsRule { workspace_resolver }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +47,11 @@ impl ExtendedLintRule for NoSloppyImportsRule {
|
|||
// do sloppy import resolution because sloppy import
|
||||
// resolution requires knowing about the surrounding files
|
||||
// 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> {
|
||||
|
@ -75,16 +72,12 @@ impl LintRule for NoSloppyImportsRule {
|
|||
let Some(workspace_resolver) = &self.workspace_resolver else {
|
||||
return;
|
||||
};
|
||||
let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver else {
|
||||
return;
|
||||
};
|
||||
if context.specifier().scheme() != "file" {
|
||||
return;
|
||||
}
|
||||
|
||||
let resolver = SloppyImportCaptureResolver {
|
||||
workspace_resolver,
|
||||
sloppy_imports_resolver,
|
||||
captures: Default::default(),
|
||||
};
|
||||
|
||||
|
@ -102,7 +95,9 @@ impl LintRule for NoSloppyImportsRule {
|
|||
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 =
|
||||
context.text_info().loc_to_source_pos(LineAndColumnIndex {
|
||||
line_index: referrer.range.start.line,
|
||||
|
@ -126,10 +121,12 @@ impl LintRule for NoSloppyImportsRule {
|
|||
custom_docs_url: Some(DOCS_URL.to_string()),
|
||||
fixes: context
|
||||
.specifier()
|
||||
.make_relative(sloppy_import.as_specifier())
|
||||
.make_relative(&specifier)
|
||||
.map(|relative| {
|
||||
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 {
|
||||
new_text: Cow::Owned({
|
||||
let relative = if relative.starts_with("../") {
|
||||
|
@ -176,8 +173,9 @@ impl LintRule for NoSloppyImportsRule {
|
|||
#[derive(Debug)]
|
||||
struct SloppyImportCaptureResolver<'a> {
|
||||
workspace_resolver: &'a WorkspaceResolver<CliSys>,
|
||||
sloppy_imports_resolver: &'a CliSloppyImportsResolver,
|
||||
captures: RefCell<HashMap<Range, SloppyImportsResolution>>,
|
||||
captures: RefCell<
|
||||
HashMap<Range, (deno_ast::ModuleSpecifier, SloppyImportsResolutionReason)>,
|
||||
>,
|
||||
}
|
||||
|
||||
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,
|
||||
match resolution_kind {
|
||||
ResolutionKind::Execution => {
|
||||
deno_config::workspace::ResolutionKind::Execution
|
||||
deno_resolver::workspace::ResolutionKind::Execution
|
||||
}
|
||||
ResolutionKind::Types => {
|
||||
deno_config::workspace::ResolutionKind::Types
|
||||
deno_resolver::workspace::ResolutionKind::Types
|
||||
}
|
||||
},
|
||||
)
|
||||
.map_err(|err| ResolveError::Other(JsErrorBox::from_err(err)))?;
|
||||
|
||||
match resolution {
|
||||
deno_config::workspace::MappedResolution::Normal {
|
||||
specifier, ..
|
||||
}
|
||||
| deno_config::workspace::MappedResolution::ImportMap {
|
||||
specifier, ..
|
||||
} => match self.sloppy_imports_resolver.resolve(
|
||||
&specifier,
|
||||
match resolution_kind {
|
||||
ResolutionKind::Execution => SloppyImportsResolutionKind::Execution,
|
||||
ResolutionKind::Types => SloppyImportsResolutionKind::Types,
|
||||
},
|
||||
) {
|
||||
Some(res) => {
|
||||
deno_resolver::workspace::MappedResolution::Normal {
|
||||
specifier,
|
||||
sloppy_reason,
|
||||
..
|
||||
} => {
|
||||
if let Some(sloppy_reason) = sloppy_reason {
|
||||
self
|
||||
.captures
|
||||
.borrow_mut()
|
||||
.entry(referrer_range.clone())
|
||||
.or_insert_with(|| res.clone());
|
||||
Ok(res.into_specifier())
|
||||
.or_insert_with(|| (specifier.clone(), sloppy_reason));
|
||||
}
|
||||
None => Ok(specifier),
|
||||
},
|
||||
deno_config::workspace::MappedResolution::WorkspaceJsrPackage {
|
||||
Ok(specifier)
|
||||
}
|
||||
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
|
||||
Err(ResolveError::Other(JsErrorBox::generic("")))
|
||||
}
|
||||
|
|
|
@ -120,7 +120,6 @@ pub async fn publish(
|
|||
}
|
||||
|
||||
let specifier_unfurler = Arc::new(SpecifierUnfurler::new(
|
||||
cli_factory.sloppy_imports_resolver()?.cloned(),
|
||||
cli_factory.workspace_resolver().await?.clone(),
|
||||
cli_options.unstable_bare_node_builtins(),
|
||||
));
|
||||
|
|
|
@ -15,9 +15,6 @@ use deno_ast::ParsedSource;
|
|||
use deno_ast::SourceRange;
|
||||
use deno_ast::SourceTextInfo;
|
||||
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::ModuleSpecifier;
|
||||
use deno_graph::DependencyDescriptor;
|
||||
|
@ -27,12 +24,13 @@ use deno_graph::StaticDependencyKind;
|
|||
use deno_graph::TypeScriptReference;
|
||||
use deno_package_json::PackageJsonDepValue;
|
||||
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_semver::Version;
|
||||
use deno_semver::VersionReq;
|
||||
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::sys::CliSys;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -190,14 +188,12 @@ enum UnfurlSpecifierError {
|
|||
}
|
||||
|
||||
pub struct SpecifierUnfurler {
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||
bare_node_builtins: bool,
|
||||
}
|
||||
|
||||
impl SpecifierUnfurler {
|
||||
pub fn new(
|
||||
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
workspace_resolver: Arc<WorkspaceResolver<CliSys>>,
|
||||
bare_node_builtins: bool,
|
||||
) -> Self {
|
||||
|
@ -206,7 +202,6 @@ impl SpecifierUnfurler {
|
|||
PackageJsonDepResolution::Enabled
|
||||
);
|
||||
Self {
|
||||
sloppy_imports_resolver,
|
||||
workspace_resolver,
|
||||
bare_node_builtins,
|
||||
}
|
||||
|
@ -216,7 +211,7 @@ impl SpecifierUnfurler {
|
|||
&self,
|
||||
referrer: &ModuleSpecifier,
|
||||
specifier: &str,
|
||||
resolution_kind: SloppyImportsResolutionKind,
|
||||
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||
text_info: &SourceTextInfo,
|
||||
range: &deno_graph::PositionRange,
|
||||
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic),
|
||||
|
@ -251,16 +246,15 @@ impl SpecifierUnfurler {
|
|||
&self,
|
||||
referrer: &ModuleSpecifier,
|
||||
specifier: &str,
|
||||
resolution_kind: SloppyImportsResolutionKind,
|
||||
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||
) -> Result<Option<String>, UnfurlSpecifierError> {
|
||||
let resolved = if let Ok(resolved) = self.workspace_resolver.resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
resolution_kind.into(),
|
||||
) {
|
||||
let resolved = if let Ok(resolved) =
|
||||
self
|
||||
.workspace_resolver
|
||||
.resolve(specifier, referrer, resolution_kind)
|
||||
{
|
||||
match resolved {
|
||||
MappedResolution::Normal { specifier, .. }
|
||||
| MappedResolution::ImportMap { specifier, .. } => Some(specifier),
|
||||
MappedResolution::Normal { specifier, .. } => Some(specifier),
|
||||
MappedResolution::WorkspaceJsrPackage { pkg_req_ref, .. } => {
|
||||
Some(ModuleSpecifier::parse(&pkg_req_ref.to_string()).unwrap())
|
||||
}
|
||||
|
@ -398,15 +392,6 @@ impl SpecifierUnfurler {
|
|||
// } else {
|
||||
// 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);
|
||||
if relative_resolved == specifier {
|
||||
Ok(None) // nothing to unfurl
|
||||
|
@ -464,7 +449,7 @@ impl SpecifierUnfurler {
|
|||
let maybe_unfurled = self.unfurl_specifier_reporting_diagnostic(
|
||||
module_url,
|
||||
specifier,
|
||||
SloppyImportsResolutionKind::Execution, // dynamic imports are always execution
|
||||
deno_resolver::workspace::ResolutionKind::Execution, // dynamic imports are always execution
|
||||
text_info,
|
||||
&dep.argument_range,
|
||||
diagnostic_reporter,
|
||||
|
@ -492,7 +477,7 @@ impl SpecifierUnfurler {
|
|||
let unfurled = self.unfurl_specifier_reporting_diagnostic(
|
||||
module_url,
|
||||
specifier,
|
||||
SloppyImportsResolutionKind::Execution, // dynamic imports are always execution
|
||||
deno_resolver::workspace::ResolutionKind::Execution, // dynamic imports are always execution
|
||||
text_info,
|
||||
&dep.argument_range,
|
||||
diagnostic_reporter,
|
||||
|
@ -538,7 +523,7 @@ impl SpecifierUnfurler {
|
|||
let analyze_specifier =
|
||||
|specifier: &str,
|
||||
range: &deno_graph::PositionRange,
|
||||
resolution_kind: SloppyImportsResolutionKind,
|
||||
resolution_kind: deno_resolver::workspace::ResolutionKind,
|
||||
text_changes: &mut Vec<deno_ast::TextChange>,
|
||||
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic)| {
|
||||
if let Some(unfurled) = self.unfurl_specifier_reporting_diagnostic(
|
||||
|
@ -559,18 +544,18 @@ impl SpecifierUnfurler {
|
|||
match dep {
|
||||
DependencyDescriptor::Static(dep) => {
|
||||
let resolution_kind = if parsed_source.media_type().is_declaration() {
|
||||
SloppyImportsResolutionKind::Types
|
||||
deno_resolver::workspace::ResolutionKind::Types
|
||||
} else {
|
||||
match dep.kind {
|
||||
StaticDependencyKind::Export
|
||||
| StaticDependencyKind::Import
|
||||
| StaticDependencyKind::ExportEquals
|
||||
| StaticDependencyKind::ImportEquals => {
|
||||
SloppyImportsResolutionKind::Execution
|
||||
deno_resolver::workspace::ResolutionKind::Execution
|
||||
}
|
||||
StaticDependencyKind::ExportType
|
||||
| StaticDependencyKind::ImportType => {
|
||||
SloppyImportsResolutionKind::Types
|
||||
deno_resolver::workspace::ResolutionKind::Types
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -616,7 +601,7 @@ impl SpecifierUnfurler {
|
|||
analyze_specifier(
|
||||
&specifier_with_range.text,
|
||||
&specifier_with_range.range,
|
||||
SloppyImportsResolutionKind::Types,
|
||||
deno_resolver::workspace::ResolutionKind::Types,
|
||||
&mut text_changes,
|
||||
diagnostic_reporter,
|
||||
);
|
||||
|
@ -625,7 +610,7 @@ impl SpecifierUnfurler {
|
|||
analyze_specifier(
|
||||
&jsdoc.specifier.text,
|
||||
&jsdoc.specifier.range,
|
||||
SloppyImportsResolutionKind::Types,
|
||||
deno_resolver::workspace::ResolutionKind::Types,
|
||||
&mut text_changes,
|
||||
diagnostic_reporter,
|
||||
);
|
||||
|
@ -634,7 +619,7 @@ impl SpecifierUnfurler {
|
|||
analyze_specifier(
|
||||
&specifier_with_range.text,
|
||||
&specifier_with_range.range,
|
||||
SloppyImportsResolutionKind::Execution,
|
||||
deno_resolver::workspace::ResolutionKind::Execution,
|
||||
&mut text_changes,
|
||||
diagnostic_reporter,
|
||||
);
|
||||
|
@ -643,7 +628,7 @@ impl SpecifierUnfurler {
|
|||
analyze_specifier(
|
||||
&specifier_with_range.text,
|
||||
&specifier_with_range.range,
|
||||
SloppyImportsResolutionKind::Types,
|
||||
deno_resolver::workspace::ResolutionKind::Types,
|
||||
&mut text_changes,
|
||||
diagnostic_reporter,
|
||||
);
|
||||
|
@ -700,7 +685,7 @@ mod tests {
|
|||
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::url::Url;
|
||||
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||
use deno_resolver::workspace::SloppyImportsOptions;
|
||||
use deno_runtime::deno_node::PackageJson;
|
||||
use deno_semver::Version;
|
||||
use import_map::ImportMapWithDiagnostics;
|
||||
|
@ -760,18 +745,14 @@ mod tests {
|
|||
exports: IndexMap::from([(".".to_string(), "mod.ts".to_string())]),
|
||||
}],
|
||||
vec![Arc::new(package_json)],
|
||||
deno_config::workspace::PackageJsonDepResolution::Enabled,
|
||||
deno_resolver::workspace::PackageJsonDepResolution::Enabled,
|
||||
SloppyImportsOptions::Enabled,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
CliSys::default(),
|
||||
);
|
||||
let unfurler = SpecifierUnfurler::new(
|
||||
Some(Arc::new(CliSloppyImportsResolver::new(
|
||||
SloppyImportsCachedFs::new(CliSys::default()),
|
||||
))),
|
||||
Arc::new(workspace_resolver),
|
||||
true,
|
||||
);
|
||||
let unfurler = SpecifierUnfurler::new(Arc::new(workspace_resolver), true);
|
||||
|
||||
// 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_publishing),
|
||||
],
|
||||
deno_config::workspace::PackageJsonDepResolution::Enabled,
|
||||
deno_resolver::workspace::PackageJsonDepResolution::Enabled,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
sys.clone(),
|
||||
);
|
||||
let unfurler = SpecifierUnfurler::new(
|
||||
Some(Arc::new(CliSloppyImportsResolver::new(
|
||||
SloppyImportsCachedFs::new(sys),
|
||||
))),
|
||||
Arc::new(workspace_resolver),
|
||||
true,
|
||||
);
|
||||
let unfurler = SpecifierUnfurler::new(Arc::new(workspace_resolver), true);
|
||||
|
||||
{
|
||||
let source_code = r#"import add from "add";
|
||||
|
|
|
@ -33,13 +33,18 @@ deno_path_util.workspace = true
|
|||
deno_semver.workspace = true
|
||||
deno_terminal.workspace = true
|
||||
futures.workspace = true
|
||||
import_map.workspace = true
|
||||
indexmap.workspace = true
|
||||
log.workspace = true
|
||||
node_resolver.workspace = true
|
||||
once_cell.workspace = true
|
||||
parking_lot.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sys_traits.workspace = true
|
||||
thiserror.workspace = true
|
||||
url.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
sys_traits = { workspace = true, features = ["memory", "real", "serde_json"] }
|
||||
test_util.workspace = true
|
||||
|
|
|
@ -12,7 +12,6 @@ use deno_cache_dir::HttpCacheRc;
|
|||
use deno_cache_dir::LocalHttpCache;
|
||||
use deno_config::deno_json::NodeModulesDirMode;
|
||||
use deno_config::workspace::FolderConfigs;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::VendorEnablement;
|
||||
use deno_config::workspace::WorkspaceDirectory;
|
||||
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
||||
|
@ -61,12 +60,13 @@ use crate::npm::NpmResolverCreateOptions;
|
|||
use crate::npmrc::discover_npmrc_from_workspace;
|
||||
use crate::npmrc::NpmRcDiscoverError;
|
||||
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::MaybeSend;
|
||||
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::DenoResolver;
|
||||
use crate::DenoResolverOptions;
|
||||
|
@ -133,7 +133,7 @@ pub trait SpecifiedImportMapProvider:
|
|||
{
|
||||
async fn get(
|
||||
&self,
|
||||
) -> Result<Option<deno_config::workspace::SpecifiedImportMap>, anyhow::Error>;
|
||||
) -> Result<Option<crate::workspace::SpecifiedImportMap>, anyhow::Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -560,7 +560,6 @@ impl<TSys: WorkspaceFactorySys> WorkspaceFactory<TSys> {
|
|||
#[derive(Debug, Default)]
|
||||
pub struct ResolverFactoryOptions {
|
||||
pub conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
||||
pub no_sloppy_imports_cache: bool,
|
||||
pub npm_system_info: NpmSystemInfo,
|
||||
pub node_resolution_cache: Option<node_resolver::NodeResolutionCacheRc>,
|
||||
pub package_json_cache: Option<node_resolver::PackageJsonCacheRc>,
|
||||
|
@ -593,8 +592,6 @@ pub struct ResolverFactory<TSys: WorkspaceFactorySys> {
|
|||
npm_resolver: Deferred<NpmResolver<TSys>>,
|
||||
npm_resolution: NpmResolutionCellRc,
|
||||
pkg_json_resolver: Deferred<PackageJsonResolverRc<TSys>>,
|
||||
sloppy_imports_resolver:
|
||||
Deferred<Option<SloppyImportsResolverRc<SloppyImportsCachedFs<TSys>>>>,
|
||||
workspace_factory: WorkspaceFactoryRc<TSys>,
|
||||
workspace_resolver: async_once_cell::OnceCell<WorkspaceResolverRc<TSys>>,
|
||||
}
|
||||
|
@ -616,7 +613,6 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
npm_resolution: Default::default(),
|
||||
npm_resolver: Default::default(),
|
||||
pkg_json_resolver: Default::default(),
|
||||
sloppy_imports_resolver: Default::default(),
|
||||
workspace_factory,
|
||||
workspace_resolver: Default::default(),
|
||||
options,
|
||||
|
@ -646,7 +642,6 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
.workspace_directory()?
|
||||
.workspace
|
||||
.vendor_dir_path(),
|
||||
sloppy_imports_resolver: self.sloppy_imports_resolver()?.cloned(),
|
||||
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(
|
||||
&self,
|
||||
) -> Result<&WorkspaceResolverRc<TSys>, anyhow::Error> {
|
||||
|
@ -815,7 +778,7 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
Some(import_map) => import_map.get().await?,
|
||||
None => None,
|
||||
};
|
||||
let options = deno_config::workspace::CreateResolverOptions {
|
||||
let options = crate::workspace::CreateResolverOptions {
|
||||
pkg_json_dep_resolution: match self
|
||||
.options
|
||||
.package_json_dep_resolution
|
||||
|
@ -834,9 +797,24 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
}
|
||||
},
|
||||
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
|
||||
.create_resolver(self.workspace_factory.sys.clone(), options)?;
|
||||
let resolver = WorkspaceResolver::from_workspace(
|
||||
workspace,
|
||||
self.workspace_factory.sys.clone(),
|
||||
options,
|
||||
)?;
|
||||
if !resolver.diagnostics().is_empty() {
|
||||
// todo(dsherret): do not log this in this crate... that should be
|
||||
// a CLI responsibility
|
||||
|
|
|
@ -7,11 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
use boxed_error::Boxed;
|
||||
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_package_json::PackageJsonDepValue;
|
||||
use deno_package_json::PackageJsonDepValueParseError;
|
||||
|
@ -31,9 +26,6 @@ use npm::NpmReqResolverRc;
|
|||
use npm::ResolveIfForNpmPackageErrorKind;
|
||||
use npm::ResolvePkgFolderFromDenoReqError;
|
||||
use npm::ResolveReqWithSubPathErrorKind;
|
||||
use sloppy_imports::SloppyImportResolverFs;
|
||||
use sloppy_imports::SloppyImportsResolutionKind;
|
||||
use sloppy_imports::SloppyImportsResolverRc;
|
||||
use sys_traits::FsCanonicalize;
|
||||
use sys_traits::FsMetadata;
|
||||
use sys_traits::FsRead;
|
||||
|
@ -41,12 +33,18 @@ use sys_traits::FsReadDir;
|
|||
use thiserror::Error;
|
||||
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 factory;
|
||||
pub mod npm;
|
||||
pub mod npmrc;
|
||||
pub mod sloppy_imports;
|
||||
mod sync;
|
||||
pub mod workspace;
|
||||
|
||||
#[allow(clippy::disallowed_types)]
|
||||
pub type WorkspaceResolverRc<TSys> =
|
||||
|
@ -128,7 +126,6 @@ pub struct DenoResolverOptions<
|
|||
TInNpmPackageChecker: InNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||
> {
|
||||
pub in_npm_pkg_checker: TInNpmPackageChecker,
|
||||
|
@ -140,8 +137,6 @@ pub struct DenoResolverOptions<
|
|||
TSys,
|
||||
>,
|
||||
>,
|
||||
pub sloppy_imports_resolver:
|
||||
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
|
||||
pub workspace_resolver: WorkspaceResolverRc<TSys>,
|
||||
/// Whether "bring your own node_modules" is enabled where Deno does not
|
||||
/// setup the node_modules directories automatically, but instead uses
|
||||
|
@ -155,14 +150,12 @@ pub type DenoResolverRc<
|
|||
TInNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs,
|
||||
TSys,
|
||||
> = crate::sync::MaybeArc<
|
||||
DenoResolver<
|
||||
TInNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs,
|
||||
TSys,
|
||||
>,
|
||||
>;
|
||||
|
@ -173,7 +166,6 @@ pub type DefaultDenoResolverRc<TSys> = DenoResolverRc<
|
|||
npm::DenoInNpmPackageChecker,
|
||||
node_resolver::DenoIsBuiltInNodeModuleChecker,
|
||||
npm::NpmResolver<TSys>,
|
||||
sloppy_imports::SloppyImportsCachedFs<TSys>,
|
||||
TSys,
|
||||
>;
|
||||
|
||||
|
@ -184,7 +176,6 @@ pub struct DenoResolver<
|
|||
TInNpmPackageChecker: InNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||
> {
|
||||
in_npm_pkg_checker: TInNpmPackageChecker,
|
||||
|
@ -196,8 +187,6 @@ pub struct DenoResolver<
|
|||
TSys,
|
||||
>,
|
||||
>,
|
||||
sloppy_imports_resolver:
|
||||
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
|
||||
workspace_resolver: WorkspaceResolverRc<TSys>,
|
||||
is_byonm: bool,
|
||||
maybe_vendor_specifier: Option<Url>,
|
||||
|
@ -207,14 +196,12 @@ impl<
|
|||
TInNpmPackageChecker: InNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs: SloppyImportResolverFs,
|
||||
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
|
||||
>
|
||||
DenoResolver<
|
||||
TInNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs,
|
||||
TSys,
|
||||
>
|
||||
{
|
||||
|
@ -223,14 +210,12 @@ impl<
|
|||
TInNpmPackageChecker,
|
||||
TIsBuiltInNodeModuleChecker,
|
||||
TNpmPackageFolderResolver,
|
||||
TSloppyImportResolverFs,
|
||||
TSys,
|
||||
>,
|
||||
) -> Self {
|
||||
Self {
|
||||
in_npm_pkg_checker: options.in_npm_pkg_checker,
|
||||
node_and_npm_resolver: options.node_and_req_resolver,
|
||||
sloppy_imports_resolver: options.sloppy_imports_resolver,
|
||||
workspace_resolver: options.workspace_resolver,
|
||||
is_byonm: options.is_byonm,
|
||||
maybe_vendor_specifier: options
|
||||
|
@ -277,33 +262,10 @@ impl<
|
|||
MappedResolution::Normal {
|
||||
specifier,
|
||||
maybe_diagnostic: current_diagnostic,
|
||||
}
|
||||
| MappedResolution::ImportMap {
|
||||
specifier,
|
||||
maybe_diagnostic: current_diagnostic,
|
||||
..
|
||||
} => {
|
||||
maybe_diagnostic = current_diagnostic;
|
||||
// do sloppy imports resolution if enabled
|
||||
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)
|
||||
}
|
||||
Ok(specifier)
|
||||
}
|
||||
MappedResolution::WorkspaceJsrPackage { 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,
|
||||
}
|
||||
|
||||
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 {
|
||||
pub fn is_types(&self) -> bool {
|
||||
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