mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(unstable): sloppy imports should resolve .d.ts files during types resolution (#22602)
This commit is contained in:
parent
8d5c231349
commit
e9fe71acb5
10 changed files with 348 additions and 135 deletions
84
Cargo.lock
generated
84
Cargo.lock
generated
|
@ -1124,9 +1124,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ast"
|
||||
version = "0.34.0"
|
||||
version = "0.34.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b28da6d573c30a63e4a6b66b91fa32773ed2cf4c0f26aa19b91f6c542b1a57"
|
||||
checksum = "a73fa2b215c93d44b55228a6c69aa92ffa200cfa683ebaf45202ecfbd749bf52"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
@ -1434,9 +1434,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_graph"
|
||||
version = "0.69.4"
|
||||
version = "0.69.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73c83b0538ee10854dcf0f24aa05ec79f62e308b358cefd65d30f9d0959a9dc3"
|
||||
checksum = "d49d7cfd7eb14200f2d91b9ff3330b7bd86334060367d47248871c78374a2897"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -2251,9 +2251,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dprint-swc-ext"
|
||||
version = "0.15.0"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fcd02c378803dba687471a9f1f1b758c33e53f616333faaddbaeb8840d9b6dd"
|
||||
checksum = "5bad772f9e49af3a613fcddf1671d1e2e877e0a6d94f2b7162bfea4ac8140bee"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"bumpalo",
|
||||
|
@ -5945,9 +5945,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_bundler"
|
||||
version = "0.225.6"
|
||||
version = "0.225.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a10c82d574fd928182f90962e280967b23b692d7e21ec9484dc6cbdaa73bab"
|
||||
checksum = "21736fd17b258d4324f576e1d151d997fd5370a04b68dcb59f3e5050828de33f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"crc",
|
||||
|
@ -5989,9 +5989,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_common"
|
||||
version = "0.33.17"
|
||||
version = "0.33.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "095c158fe55b36faeebb4274692643a6d7cdc5b7902e1d5968ddbe52b7de1d1c"
|
||||
checksum = "c85e8b15d0fb87691e27c8f3cf953748db3ccd2a39e165d6d5275a48fb0d29e3"
|
||||
dependencies = [
|
||||
"ast_node",
|
||||
"better_scoped_tls",
|
||||
|
@ -6041,9 +6041,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.112.2"
|
||||
version = "0.112.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852a48a24a2533de88298c6b25355bc68fdee31ac21cb4fb8939b7001715353c"
|
||||
checksum = "36226eb87bfd2f5620bde04f149a4b869ab34e78496d60cb0d8eb9da765d0732"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"is-macro",
|
||||
|
@ -6059,9 +6059,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_codegen"
|
||||
version = "0.148.3"
|
||||
version = "0.148.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d79df3f8c5ed028fce5dc24acb83002c0854f8b9d7e893292aeee394a6b9eaf4"
|
||||
checksum = "5ba8669ab28bb5d1e65c1e8690257c026745ac368e0101c2c6544d4a03afc95e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"num-bigint",
|
||||
|
@ -6090,9 +6090,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_loader"
|
||||
version = "0.45.19"
|
||||
version = "0.45.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c16051bce5421992a1b49350735bf4d110f761fd68ae7098af17a64ad639b8d"
|
||||
checksum = "d0058cf970880f5382effe43eb2b727a73ba09ae41922fa140c2c3fa6ca9b2d1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"pathdiff",
|
||||
|
@ -6104,9 +6104,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.143.3"
|
||||
version = "0.143.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ff55811ed5de14b05e9a2979bae2bce3c807582f559b4325948463265307d9"
|
||||
checksum = "20823cac99a9adbd4c03fb5e126aaccbf92446afedad99252a0e1fc76e2ffc43"
|
||||
dependencies = [
|
||||
"either",
|
||||
"new_debug_unreachable",
|
||||
|
@ -6126,9 +6126,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_base"
|
||||
version = "0.137.6"
|
||||
version = "0.137.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9489f8f5c6c08e8291bd93eb354aa91903d4eba5eeb72e1b90adf43c8fe7a29"
|
||||
checksum = "66539401f619730b26d380a120b91b499f80cbdd9bb15d00aa73bc3a4d4cc394"
|
||||
dependencies = [
|
||||
"better_scoped_tls",
|
||||
"bitflags 2.4.1",
|
||||
|
@ -6149,9 +6149,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_classes"
|
||||
version = "0.126.6"
|
||||
version = "0.126.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00fecbd333497362f75f475ca467beb486ae381968c9bd67315dddacc9ee67c"
|
||||
checksum = "ebf9048e687b746d2bbe6149601c3eedd819fef08d7657e5fddcef99b22febba"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
|
@ -6175,9 +6175,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_optimization"
|
||||
version = "0.198.6"
|
||||
version = "0.198.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db73c718c737c58ed7265fea79aff38578012269398d856264ddc4e764dfb192"
|
||||
checksum = "17889816334ce9d05ab0c292f93514fdd863b8537a35852dda609ebe3f48071d"
|
||||
dependencies = [
|
||||
"dashmap",
|
||||
"indexmap",
|
||||
|
@ -6199,9 +6199,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_proposal"
|
||||
version = "0.171.6"
|
||||
version = "0.171.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39920f44aa30ab997dd7cfdc364addd54e4a5fcc3807ae69a6fe283f306bc5a5"
|
||||
checksum = "35f0a72ee781aa9208836046fd2c12e483f5515898858511b68863290cb97b45"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rustc-hash",
|
||||
|
@ -6219,9 +6219,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_react"
|
||||
version = "0.183.6"
|
||||
version = "0.183.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d8d36fc8dbfd96dd1ef17f989175e60a291399c6168b20a74951085b0075df"
|
||||
checksum = "f0ec75c1194365abe4d44d94e58f918ec853469ecd39733b381a089cfdcdee1a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"dashmap",
|
||||
|
@ -6243,9 +6243,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_typescript"
|
||||
version = "0.188.6"
|
||||
version = "0.188.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "432cf63b05d3ec435199bfbf7ba50793c6cb777bfcd8ad9f055f501aa9048d9c"
|
||||
checksum = "fec5e95a9c840eb13562884123eaa627cb6e05e0461c94a2ce69ae7e70313010"
|
||||
dependencies = [
|
||||
"ryu-js",
|
||||
"serde",
|
||||
|
@ -6260,9 +6260,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.127.5"
|
||||
version = "0.127.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2de25ac5cc8c8375476985e854054f05d9e841886f3c290716a0eec32eedce3"
|
||||
checksum = "14482e455df85486d68a51533a31645d511e56df93a35cadf0eabbe7abe96b98"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"num_cpus",
|
||||
|
@ -6278,9 +6278,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_visit"
|
||||
version = "0.98.2"
|
||||
version = "0.98.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb71511a816c7c84ddc96e6939389be261caf20858486a5e76948551f110e1f"
|
||||
checksum = "df0127694c36d656ea9eab5c170cdd8ab398246ae2a335de26961c913a4aca47"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"swc_atoms",
|
||||
|
@ -6303,9 +6303,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_fast_graph"
|
||||
version = "0.21.17"
|
||||
version = "0.21.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffd32eda2dd2c725f8d4448d0013c3b5466118e4ff5c30aff2c04f6750f7238b"
|
||||
checksum = "91bea847755eb7b131edb83c1a437d353e9d25cabd92ac27655420dd13c7267b"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"petgraph",
|
||||
|
@ -6315,9 +6315,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_graph_analyzer"
|
||||
version = "0.22.19"
|
||||
version = "0.22.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ae1172960aa3b0cdbe94a1d5edf3efa9f1199cbd8384f48dedd0c5bdb5d6bd"
|
||||
checksum = "1f1469d9d6d5c6f3b469348262ab6bda2c8a9d8e3db7298d9f71f6d17986895d"
|
||||
dependencies = [
|
||||
"auto_impl",
|
||||
"petgraph",
|
||||
|
@ -6339,9 +6339,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_visit"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b27078d8571abe23aa52ef608dd1df89096a37d867cf691cbb4f4c392322b7c9"
|
||||
checksum = "358e246dedeb4ae8efacebcce1360dc2f9b6c0b4c1ad8b737cc60f5b6633691a"
|
||||
dependencies = [
|
||||
"either",
|
||||
"swc_visit_macros",
|
||||
|
@ -6349,9 +6349,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_visit_macros"
|
||||
version = "0.5.9"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa8bb05975506741555ea4d10c3a3bdb0e2357cd58e1a4a4332b8ebb4b44c34d"
|
||||
checksum = "fbbbb9d77d5112f90ed7ea00477135b16c4370c872b93a0b63b766e8710650ad"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"pmutil",
|
||||
|
|
|
@ -42,7 +42,7 @@ license = "MIT"
|
|||
repository = "https://github.com/denoland/deno"
|
||||
|
||||
[workspace.dependencies]
|
||||
deno_ast = { version = "0.34.0", features = ["transpiling"] }
|
||||
deno_ast = { version = "0.34.1", features = ["transpiling"] }
|
||||
deno_core = { version = "0.265.0", features = ["snapshot_data_bincode"] }
|
||||
|
||||
deno_bench_util = { version = "0.133.0", path = "./bench_util" }
|
||||
|
|
|
@ -68,7 +68,7 @@ deno_config = "=0.12.0"
|
|||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||
deno_doc = { version = "=0.113.1", features = ["html"] }
|
||||
deno_emit = "=0.38.2"
|
||||
deno_graph = { version = "=0.69.4", features = ["tokio_executor"] }
|
||||
deno_graph = { version = "=0.69.5", features = ["tokio_executor"] }
|
||||
deno_lint = { version = "=0.57.1", features = ["docs"] }
|
||||
deno_lockfile.workspace = true
|
||||
deno_npm = "=0.17.0"
|
||||
|
|
|
@ -30,6 +30,7 @@ use deno_core::parking_lot::Mutex;
|
|||
use deno_core::parking_lot::RwLock;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_graph::source::Loader;
|
||||
use deno_graph::source::ResolutionMode;
|
||||
use deno_graph::source::ResolveError;
|
||||
use deno_graph::GraphKind;
|
||||
use deno_graph::Module;
|
||||
|
@ -694,8 +695,12 @@ pub fn enhanced_module_error_message(
|
|||
) -> String {
|
||||
let additional_message = match error {
|
||||
ModuleError::Missing(specifier, _) => {
|
||||
SloppyImportsResolver::resolve_with_fs(fs, specifier)
|
||||
.as_suggestion_message()
|
||||
SloppyImportsResolver::resolve_with_fs(
|
||||
fs,
|
||||
specifier,
|
||||
ResolutionMode::Execution,
|
||||
)
|
||||
.as_suggestion_message()
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ use deno_core::unsync::spawn;
|
|||
use deno_core::unsync::spawn_blocking;
|
||||
use deno_core::unsync::JoinHandle;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_graph::source::ResolutionMode;
|
||||
use deno_graph::Resolution;
|
||||
use deno_graph::ResolutionError;
|
||||
use deno_graph::SpecifierError;
|
||||
|
@ -1240,7 +1241,7 @@ impl DenoDiagnostic {
|
|||
Self::NoCacheJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing jsr package: {}", pkg_req), Some(json!({ "specifier": specifier }))),
|
||||
Self::NoCacheNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: {}", pkg_req), Some(json!({ "specifier": specifier }))),
|
||||
Self::NoLocal(specifier) => {
|
||||
let sloppy_resolution = SloppyImportsResolver::resolve_with_fs(&deno_fs::RealFs, specifier);
|
||||
let sloppy_resolution = SloppyImportsResolver::resolve_with_fs(&deno_fs::RealFs, specifier, ResolutionMode::Execution);
|
||||
let data = sloppy_resolution.as_lsp_quick_fix_message().map(|message| {
|
||||
json!({
|
||||
"specifier": specifier,
|
||||
|
|
|
@ -1101,24 +1101,28 @@ impl Documents {
|
|||
&self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
) -> SloppyImportsResolution<'a> {
|
||||
SloppyImportsResolver::resolve_with_stat_sync(specifier, |path| {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(path) {
|
||||
if self.open_docs.contains_key(&specifier)
|
||||
|| self.cache.contains(&specifier)
|
||||
{
|
||||
return Some(SloppyImportsFsEntry::File);
|
||||
SloppyImportsResolver::resolve_with_stat_sync(
|
||||
specifier,
|
||||
ResolutionMode::Types,
|
||||
|path| {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(path) {
|
||||
if self.open_docs.contains_key(&specifier)
|
||||
|| self.cache.contains(&specifier)
|
||||
{
|
||||
return Some(SloppyImportsFsEntry::File);
|
||||
}
|
||||
}
|
||||
}
|
||||
path.metadata().ok().and_then(|m| {
|
||||
if m.is_file() {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if m.is_dir() {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
path.metadata().ok().and_then(|m| {
|
||||
if m.is_file() {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if m.is_dir() {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Return `true` if the specifier can be resolved to a document.
|
||||
|
@ -1800,22 +1804,26 @@ impl<'a> OpenDocumentsGraphLoader<'a> {
|
|||
&self,
|
||||
specifier: &'b ModuleSpecifier,
|
||||
) -> SloppyImportsResolution<'b> {
|
||||
SloppyImportsResolver::resolve_with_stat_sync(specifier, |path| {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(path) {
|
||||
if self.open_docs.contains_key(&specifier) {
|
||||
return Some(SloppyImportsFsEntry::File);
|
||||
SloppyImportsResolver::resolve_with_stat_sync(
|
||||
specifier,
|
||||
ResolutionMode::Types,
|
||||
|path| {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(path) {
|
||||
if self.open_docs.contains_key(&specifier) {
|
||||
return Some(SloppyImportsFsEntry::File);
|
||||
}
|
||||
}
|
||||
}
|
||||
path.metadata().ok().and_then(|m| {
|
||||
if m.is_file() {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if m.is_dir() {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
path.metadata().ok().and_then(|m| {
|
||||
if m.is_file() {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if m.is_dir() {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
205
cli/resolver.rs
205
cli/resolver.rs
|
@ -522,6 +522,7 @@ impl Resolver for CliGraphResolver {
|
|||
sloppy_imports_resolver,
|
||||
specifier,
|
||||
referrer_range,
|
||||
mode,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
|
@ -646,12 +647,22 @@ fn sloppy_imports_resolve(
|
|||
resolver: &SloppyImportsResolver,
|
||||
specifier: ModuleSpecifier,
|
||||
referrer_range: &deno_graph::Range,
|
||||
mode: ResolutionMode,
|
||||
) -> ModuleSpecifier {
|
||||
let resolution = resolver.resolve(&specifier);
|
||||
let resolution = resolver.resolve(&specifier, mode);
|
||||
if mode.is_types() {
|
||||
// don't bother warning for types resolution because
|
||||
// we already probably warned during execution resolution
|
||||
match resolution {
|
||||
SloppyImportsResolution::None(_) => return specifier, // avoid a clone
|
||||
_ => return resolution.into_specifier().into_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
let hint_message = match &resolution {
|
||||
SloppyImportsResolution::JsToTs(to_specifier) => {
|
||||
let from_media_type = MediaType::from_specifier(&specifier);
|
||||
let to_media_type = MediaType::from_specifier(to_specifier);
|
||||
let from_media_type = MediaType::from_specifier(&specifier);
|
||||
format!(
|
||||
"update {} extension to {}",
|
||||
from_media_type.as_ts_extension(),
|
||||
|
@ -677,7 +688,7 @@ fn sloppy_imports_resolve(
|
|||
log::warn!(
|
||||
"{} Sloppy module resolution {}\n at {}",
|
||||
crate::colors::yellow("Warning"),
|
||||
crate::colors::gray(format!("(hint: {})", hint_message)),
|
||||
crate::colors::gray(format!("(hint: {})", hint_message)).to_string(),
|
||||
if referrer_range.end == deno_graph::Position::zeroed() {
|
||||
// not worth showing the range in this case
|
||||
crate::colors::cyan(referrer_range.specifier.as_str()).to_string()
|
||||
|
@ -928,8 +939,9 @@ impl SloppyImportsResolver {
|
|||
pub fn resolve_with_fs<'a>(
|
||||
fs: &dyn FileSystem,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
) -> SloppyImportsResolution<'a> {
|
||||
Self::resolve_with_stat_sync(specifier, |path| {
|
||||
Self::resolve_with_stat_sync(specifier, mode, |path| {
|
||||
fs.stat_sync(path)
|
||||
.ok()
|
||||
.and_then(|stat| SloppyImportsFsEntry::from_fs_stat(&stat))
|
||||
|
@ -938,8 +950,38 @@ impl SloppyImportsResolver {
|
|||
|
||||
pub fn resolve_with_stat_sync(
|
||||
specifier: &ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
stat_sync: impl Fn(&Path) -> Option<SloppyImportsFsEntry>,
|
||||
) -> 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,
|
||||
probe_media_type_types: Vec<MediaType>,
|
||||
) -> Vec<PathBuf> {
|
||||
probe_media_type_types
|
||||
.into_iter()
|
||||
.map(|media_type| {
|
||||
PathBuf::from(format!(
|
||||
"{}{}",
|
||||
path_no_ext,
|
||||
media_type.as_ts_extension()
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
if specifier.scheme() != "file" {
|
||||
return SloppyImportsResolution::None(specifier);
|
||||
}
|
||||
|
@ -951,27 +993,79 @@ impl SloppyImportsResolver {
|
|||
let mut is_no_ext_resolution = false;
|
||||
let probe_paths = match (stat_sync)(&path) {
|
||||
Some(SloppyImportsFsEntry::File) => {
|
||||
return SloppyImportsResolution::None(specifier);
|
||||
if mode.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 SloppyImportsResolution::None(specifier),
|
||||
};
|
||||
let Some(path_no_ext) = path_without_ext(&path, media_type) else {
|
||||
return SloppyImportsResolution::None(specifier);
|
||||
};
|
||||
media_types_to_paths(&path_no_ext, probe_media_type_types)
|
||||
} else {
|
||||
return SloppyImportsResolution::None(specifier);
|
||||
}
|
||||
}
|
||||
Some(SloppyImportsFsEntry::Dir) => {
|
||||
is_dir_resolution = true;
|
||||
// try to resolve at the index file
|
||||
vec![
|
||||
path.join("index.ts"),
|
||||
path.join("index.js"),
|
||||
path.join("index.mts"),
|
||||
path.join("index.mjs"),
|
||||
path.join("index.tsx"),
|
||||
path.join("index.jsx"),
|
||||
]
|
||||
if mode.is_types() {
|
||||
vec![
|
||||
path.join("index.ts"),
|
||||
path.join("index.mts"),
|
||||
path.join("index.d.ts"),
|
||||
path.join("index.d.mts"),
|
||||
path.join("index.js"),
|
||||
path.join("index.mjs"),
|
||||
path.join("index.tsx"),
|
||||
path.join("index.jsx"),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
path.join("index.ts"),
|
||||
path.join("index.mts"),
|
||||
path.join("index.tsx"),
|
||||
path.join("index.js"),
|
||||
path.join("index.mjs"),
|
||||
path.join("index.jsx"),
|
||||
]
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
let probe_media_type_types = match media_type {
|
||||
MediaType::JavaScript => vec![MediaType::TypeScript, MediaType::Tsx],
|
||||
MediaType::JavaScript => {
|
||||
if mode.is_types() {
|
||||
vec![MediaType::TypeScript, MediaType::Tsx, MediaType::Dts]
|
||||
} else {
|
||||
vec![MediaType::TypeScript, MediaType::Tsx]
|
||||
}
|
||||
}
|
||||
MediaType::Jsx => vec![MediaType::Tsx],
|
||||
MediaType::Mjs => vec![MediaType::Mts],
|
||||
MediaType::Cjs => vec![MediaType::Cts],
|
||||
MediaType::Mjs => {
|
||||
if mode.is_types() {
|
||||
vec![MediaType::Mts, MediaType::Dmts, MediaType::Dts]
|
||||
} else {
|
||||
vec![MediaType::Mts]
|
||||
}
|
||||
}
|
||||
MediaType::Cjs => {
|
||||
if mode.is_types() {
|
||||
vec![MediaType::Cts, MediaType::Dcts, MediaType::Dts]
|
||||
} else {
|
||||
vec![MediaType::Cts]
|
||||
}
|
||||
}
|
||||
MediaType::TypeScript
|
||||
| MediaType::Mts
|
||||
| MediaType::Cts
|
||||
|
@ -987,34 +1081,34 @@ impl SloppyImportsResolver {
|
|||
}
|
||||
MediaType::Unknown => {
|
||||
is_no_ext_resolution = true;
|
||||
vec![
|
||||
MediaType::TypeScript,
|
||||
MediaType::JavaScript,
|
||||
MediaType::Tsx,
|
||||
MediaType::Jsx,
|
||||
MediaType::Mts,
|
||||
MediaType::Mjs,
|
||||
]
|
||||
if mode.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,
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
let old_path_str = path.to_string_lossy();
|
||||
let old_path_str = match media_type {
|
||||
MediaType::Unknown => old_path_str,
|
||||
_ => match old_path_str.strip_suffix(media_type.as_ts_extension()) {
|
||||
Some(s) => Cow::Borrowed(s),
|
||||
None => return SloppyImportsResolution::None(specifier),
|
||||
},
|
||||
let Some(path_no_ext) = path_without_ext(&path, media_type) else {
|
||||
return SloppyImportsResolution::None(specifier);
|
||||
};
|
||||
probe_media_type_types
|
||||
.into_iter()
|
||||
.map(|media_type| {
|
||||
PathBuf::from(format!(
|
||||
"{}{}",
|
||||
old_path_str,
|
||||
media_type.as_ts_extension()
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
media_types_to_paths(&path_no_ext, probe_media_type_types)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1038,8 +1132,9 @@ impl SloppyImportsResolver {
|
|||
pub fn resolve<'a>(
|
||||
&self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
) -> SloppyImportsResolution<'a> {
|
||||
Self::resolve_with_stat_sync(specifier, |path| {
|
||||
Self::resolve_with_stat_sync(specifier, mode, |path| {
|
||||
self.stat_cache.stat_sync(path)
|
||||
})
|
||||
}
|
||||
|
@ -1117,17 +1212,21 @@ mod test {
|
|||
#[test]
|
||||
fn test_unstable_sloppy_imports() {
|
||||
fn resolve(specifier: &ModuleSpecifier) -> SloppyImportsResolution {
|
||||
SloppyImportsResolver::resolve_with_stat_sync(specifier, |path| {
|
||||
RealFs.stat_sync(path).ok().and_then(|stat| {
|
||||
if stat.is_file {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if stat.is_directory {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
SloppyImportsResolver::resolve_with_stat_sync(
|
||||
specifier,
|
||||
ResolutionMode::Execution,
|
||||
|path| {
|
||||
RealFs.stat_sync(path).ok().and_then(|stat| {
|
||||
if stat.is_file {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if stat.is_directory {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
let context = TestContext::default();
|
||||
|
|
|
@ -151,7 +151,7 @@ impl<'a> SpecifierUnfurler<'a> {
|
|||
let resolved =
|
||||
if let Some(sloppy_imports_resolver) = self.sloppy_imports_resolver {
|
||||
sloppy_imports_resolver
|
||||
.resolve(&resolved)
|
||||
.resolve(&resolved, deno_graph::source::ResolutionMode::Execution)
|
||||
.as_specifier()
|
||||
.clone()
|
||||
} else {
|
||||
|
|
|
@ -418,3 +418,105 @@ fn npm_module_check_then_error() {
|
|||
.assert_matches_text("Check [WILDCARD]main.ts\nerror: TS2305[WILDCARD]has no exported member 'oldName'[WILDCARD]")
|
||||
.assert_exit_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unstable_sloppy_imports_dts_files() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
let temp_dir = context.temp_dir();
|
||||
temp_dir.write("a.ts", "export class A {}"); // resolves this
|
||||
temp_dir.write("a.d.ts", "export class A2 {}");
|
||||
|
||||
temp_dir.write("b.js", "export class B {}");
|
||||
temp_dir.write("b.d.ts", "export class B2 {}"); // this
|
||||
|
||||
temp_dir.write("c.mts", "export class C {}"); // this
|
||||
temp_dir.write("c.d.mts", "export class C2 {}");
|
||||
|
||||
temp_dir.write("d.mjs", "export class D {}");
|
||||
temp_dir.write("d.d.mts", "export class D2 {}"); // this
|
||||
|
||||
let temp_dir = temp_dir.path();
|
||||
|
||||
let dir = temp_dir.join("dir_ts");
|
||||
dir.create_dir_all();
|
||||
dir.join("index.ts").write("export class Dir {}"); // this
|
||||
dir.join("index.d.ts").write("export class Dir2 {}");
|
||||
|
||||
let dir = temp_dir.join("dir_js");
|
||||
dir.create_dir_all();
|
||||
dir.join("index.js").write("export class Dir {}");
|
||||
dir.join("index.d.ts").write("export class Dir2 {}"); // this
|
||||
|
||||
let dir = temp_dir.join("dir_mts");
|
||||
dir.create_dir_all();
|
||||
dir.join("index.mts").write("export class Dir {}"); // this
|
||||
dir.join("index.d.ts").write("export class Dir2 {}");
|
||||
|
||||
let dir = temp_dir.join("dir_mjs");
|
||||
dir.create_dir_all();
|
||||
dir.join("index.mjs").write("export class Dir {}");
|
||||
dir.join("index.d.ts").write("export class Dir2 {}"); // this
|
||||
|
||||
temp_dir.join("main.ts").write(
|
||||
r#"import * as a from "./a.js";
|
||||
import * as b from "./b.js";
|
||||
import * as c from "./c.mjs";
|
||||
import * as d from "./d.mjs";
|
||||
|
||||
console.log(a.A);
|
||||
console.log(b.B2);
|
||||
console.log(c.C);
|
||||
console.log(d.D2);
|
||||
|
||||
import * as a2 from "./a";
|
||||
import * as b2 from "./b";
|
||||
import * as c2 from "./c";
|
||||
import * as d2 from "./d";
|
||||
|
||||
console.log(a2.A);
|
||||
console.log(b2.B2);
|
||||
console.log(c2.C);
|
||||
console.log(d2.D2);
|
||||
|
||||
import * as dirTs from "./dir_ts";
|
||||
import * as dirJs from "./dir_js";
|
||||
import * as dirMts from "./dir_mts";
|
||||
import * as dirMjs from "./dir_mjs";
|
||||
|
||||
console.log(dirTs.Dir);
|
||||
console.log(dirJs.Dir2);
|
||||
console.log(dirMts.Dir);
|
||||
console.log(dirMjs.Dir2);
|
||||
"#,
|
||||
);
|
||||
|
||||
context
|
||||
.new_command()
|
||||
.args("check --unstable-sloppy-imports main.ts")
|
||||
.run()
|
||||
.assert_matches_text(
|
||||
r#"Warning Sloppy module resolution (hint: update .js extension to .ts)
|
||||
at file:///[WILDCARD]/main.ts:1:20
|
||||
Warning Sloppy module resolution (hint: update .mjs extension to .mts)
|
||||
at file:///[WILDCARD]/main.ts:3:20
|
||||
Warning Sloppy module resolution (hint: add .ts extension)
|
||||
at file:///[WILDCARD]/main.ts:11:21
|
||||
Warning Sloppy module resolution (hint: add .js extension)
|
||||
at file:///[WILDCARD]/main.ts:12:21
|
||||
Warning Sloppy module resolution (hint: add .mts extension)
|
||||
at file:///[WILDCARD]/main.ts:13:21
|
||||
Warning Sloppy module resolution (hint: add .mjs extension)
|
||||
at file:///[WILDCARD]/main.ts:14:21
|
||||
Warning Sloppy module resolution (hint: specify path to index.ts file in directory instead)
|
||||
at file:///[WILDCARD]/main.ts:21:24
|
||||
Warning Sloppy module resolution (hint: specify path to index.js file in directory instead)
|
||||
at file:///[WILDCARD]/main.ts:22:24
|
||||
Warning Sloppy module resolution (hint: specify path to index.mts file in directory instead)
|
||||
at file:///[WILDCARD]/main.ts:23:25
|
||||
Warning Sloppy module resolution (hint: specify path to index.mjs file in directory instead)
|
||||
at file:///[WILDCARD]/main.ts:24:25
|
||||
Check [WILDCARD]main.ts
|
||||
"#,
|
||||
)
|
||||
.assert_exit_code(0);
|
||||
}
|
||||
|
|
2
tests/testdata/publish/sloppy_imports.out
vendored
2
tests/testdata/publish/sloppy_imports.out
vendored
|
@ -1,5 +1,3 @@
|
|||
Warning Sloppy module resolution (hint: specify path to index.ts file in directory instead)
|
||||
at file:///[WILDCARD]/publish/sloppy_imports/mod.ts:1:20
|
||||
Warning Sloppy module resolution (hint: specify path to index.ts file in directory instead)
|
||||
at file:///[WILDCARD]/publish/sloppy_imports/mod.ts:1:20
|
||||
Check file:///[WILDCARD]/publish/sloppy_imports/mod.ts
|
||||
|
|
Loading…
Reference in a new issue