diff --git a/src/error.rs b/src/error.rs index b00a0ba8..ce46f4b0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -47,8 +47,14 @@ pub enum ResolveError { Builtin(String), /// All of the aliased extension are not found - #[error("All of the aliased extensions are not found for {0}")] - ExtensionAlias(PathBuf), + /// + /// Displays `Cannot resolve 'index.mjs' with extension aliases 'index.mts' in ...` + #[error("Cannot resolve '{0}' for extension aliases '{1}' in '{2}'")] + ExtensionAlias( + /* File name */ String, + /* Tried file names */ String, + /* Path to dir */ PathBuf, + ), /// The provided path specifier cannot be parsed #[error("{0}")] diff --git a/src/lib.rs b/src/lib.rs index e6cb2246..cacabbaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1047,11 +1047,12 @@ impl ResolverGeneric { else { return Ok(None); }; - let path = cached_path.path().with_extension(""); - let path = path.as_os_str(); + let path = cached_path.path(); + let Some(filename) = path.file_name() else { return Ok(None) }; + let path_without_extension = path.with_extension(""); ctx.with_fully_specified(true); for extension in extensions { - let mut path_with_extension = path.to_os_string(); + let mut path_with_extension = path_without_extension.clone().into_os_string(); path_with_extension.reserve_exact(extension.len()); path_with_extension.push(extension); let cached_path = self.cache.value(Path::new(&path_with_extension)); @@ -1065,7 +1066,16 @@ impl ResolverGeneric { return Ok(Some(path)); } } - Err(ResolveError::ExtensionAlias(cached_path.to_path_buf())) + // Create a meaningful error message. + let dir = path.parent().unwrap().to_path_buf(); + let filename_without_extension = Path::new(filename).with_extension(""); + let filename_without_extension = filename_without_extension.to_string_lossy(); + let files = extensions + .iter() + .map(|ext| format!("{filename_without_extension}{ext}")) + .collect::>() + .join(","); + Err(ResolveError::ExtensionAlias(filename.to_string_lossy().to_string(), files, dir)) } /// enhanced-resolve: RootsPlugin diff --git a/src/tests/exports_field.rs b/src/tests/exports_field.rs index 7ca73fbd..8f3cb4d8 100644 --- a/src/tests/exports_field.rs +++ b/src/tests/exports_field.rs @@ -269,7 +269,7 @@ fn extension_alias_throw_error() { let fail = [ // enhanced-resolve has two test cases that are exactly the same here // https://github.com/webpack/enhanced-resolve/blob/a998c7d218b7a9ec2461fc4fddd1ad5dd7687485/test/exportsField.test.js#L2976-L3024 - ("should throw error with the `extensionAlias` option", f.clone(), "pkg/string.js", ResolveError::ExtensionAlias(f.join("node_modules/pkg/dist/string.js"))), + ("should throw error with the `extensionAlias` option", f.clone(), "pkg/string.js", ResolveError::ExtensionAlias("string.js".into(), "string.ts".into(), f.join("node_modules/pkg/dist"))), // TODO: The error is PackagePathNotExported in enhanced-resolve // ("should throw error with the `extensionAlias` option", f.clone(), "pkg/string.js", ResolveError::PackagePathNotExported("node_modules/pkg/dist/string.ts".to_string())), ]; diff --git a/src/tests/extension_alias.rs b/src/tests/extension_alias.rs index cc6a906b..cf4fd362 100644 --- a/src/tests/extension_alias.rs +++ b/src/tests/extension_alias.rs @@ -29,19 +29,10 @@ fn extension_alias() { assert_eq!(resolved_path, Ok(expected), "{comment} {path:?} {request}"); } - #[rustfmt::skip] - let fail = [ - ("should not allow to fallback to the original extension or add extensions", f.clone(), "./index.mjs"), - ]; - - for (comment, path, request) in fail { - let resolution = resolver.resolve(&path, request); - assert_eq!( - resolution, - Err(ResolveError::ExtensionAlias(f.join(request))), - "{comment} {path:?} {request}" - ); - } + // should not allow to fallback to the original extension or add extensions + let resolution = resolver.resolve(&f, "./index.mjs").unwrap_err(); + let expected = ResolveError::ExtensionAlias("index.mjs".into(), "index.mts".into(), f); + assert_eq!(resolution, expected); } // should not apply extension alias to extensions or mainFiles field