diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 65a23fce6d..04154d3caf 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -14497,6 +14497,36 @@ func (c *Checker) resolveExternalModule(location *ast.Node, moduleReference stri tsExtension, ) } + } else if c.compilerOptions.RewriteRelativeImportExtensions.IsTrue() && + location.Flags&ast.NodeFlagsAmbient == 0 && + !tspath.IsDeclarationFileName(moduleReference) && + !ast.IsLiteralImportTypeNode(location) && + !ast.IsPartOfTypeOnlyImportOrExportDeclaration(location) { + shouldRewrite := tspath.ShouldRewriteModuleSpecifier(moduleReference, c.compilerOptions.RewriteRelativeImportExtensions.IsTrue()) + if !resolvedModule.ResolvedUsingTsExtension && shouldRewrite { + // Get relative path from current source file to resolved file + sourceFileDir := tspath.GetDirectoryPath(importingSourceFile.FileName()) + targetPath := resolvedModule.ResolvedFileName + canonicalSourceDir := tspath.GetCanonicalFileName(sourceFileDir, !c.program.UseCaseSensitiveFileNames()) + canonicalTargetPath := tspath.GetCanonicalFileName(targetPath, !c.program.UseCaseSensitiveFileNames()) + relativePath := tspath.GetRelativePathFromDirectory(canonicalSourceDir, canonicalTargetPath, tspath.ComparePathsOptions{ + CurrentDirectory: c.program.GetCurrentDirectory(), + UseCaseSensitiveFileNames: c.program.UseCaseSensitiveFileNames(), + }) + c.error( + errorNode, + diagnostics.This_relative_import_path_is_unsafe_to_rewrite_because_it_looks_like_a_file_name_but_actually_resolves_to_0, + relativePath, + ) + } else if resolvedModule.ResolvedUsingTsExtension && !shouldRewrite { + // For now, we'll skip the sourceFileMayBeEmitted check to keep it simple + c.error( + errorNode, + diagnostics.This_import_uses_a_0_extension_to_resolve_to_an_input_TypeScript_file_but_will_not_be_rewritten_during_emit_because_it_is_not_a_relative_path, + tspath.GetAnyExtensionFromPath(moduleReference, nil, !c.program.UseCaseSensitiveFileNames()), + ) + } + // TODO: Add project reference validation for the third error case } } diff --git a/internal/transformers/utilities.go b/internal/transformers/utilities.go index 9114ae674f..0cf5bb16a4 100644 --- a/internal/transformers/utilities.go +++ b/internal/transformers/utilities.go @@ -336,7 +336,7 @@ func tryRenameExternalModule(factory *printer.NodeFactory, moduleName *ast.Liter } func rewriteModuleSpecifier(emitContext *printer.EmitContext, node *ast.Expression, compilerOptions *core.CompilerOptions) *ast.Expression { - if node == nil || !ast.IsStringLiteral(node) || !shouldRewriteModuleSpecifier(node.Text(), compilerOptions) { + if node == nil || !ast.IsStringLiteral(node) || !tspath.ShouldRewriteModuleSpecifier(node.Text(), compilerOptions.RewriteRelativeImportExtensions.IsTrue()) { return node } updatedText := tspath.ChangeExtension(node.Text(), outputpaths.GetOutputExtension(node.Text(), compilerOptions.Jsx)) @@ -350,10 +350,6 @@ func rewriteModuleSpecifier(emitContext *printer.EmitContext, node *ast.Expressi return node } -func shouldRewriteModuleSpecifier(specifier string, compilerOptions *core.CompilerOptions) bool { - return compilerOptions.RewriteRelativeImportExtensions.IsTrue() && tspath.PathIsRelative(specifier) && !tspath.IsDeclarationFileName(specifier) && tspath.HasTSFileExtension(specifier) -} - func singleOrMany(nodes []*ast.Node, factory *printer.NodeFactory) *ast.Node { if len(nodes) == 1 { return nodes[0] diff --git a/internal/tsoptions/declscompiler.go b/internal/tsoptions/declscompiler.go index 4b32a19ab0..c378ad896a 100644 --- a/internal/tsoptions/declscompiler.go +++ b/internal/tsoptions/declscompiler.go @@ -810,8 +810,8 @@ var commonOptionsWithBuild = []*CommandLineOption{ AffectsSemanticDiagnostics: true, AffectsBuildInfo: true, Category: diagnostics.Modules, - // description: diagnostics.Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_in_output_files, - DefaultValueDescription: false, + Description: diagnostics.Rewrite_ts_tsx_mts_and_cts_file_extensions_in_relative_import_paths_to_their_JavaScript_equivalent_in_output_files, + DefaultValueDescription: false, }, { Name: "resolvePackageJsonExports", diff --git a/internal/tspath/path.go b/internal/tspath/path.go index caf1740cac..e3081f4fce 100644 --- a/internal/tspath/path.go +++ b/internal/tspath/path.go @@ -902,3 +902,7 @@ func ForEachAncestorDirectoryPath[T any](directory Path, callback func(directory func HasExtension(fileName string) bool { return strings.Contains(GetBaseFileName(fileName), ".") } + +func ShouldRewriteModuleSpecifier(specifier string, rewriteRelativeImportExtensions bool) bool { + return rewriteRelativeImportExtensions && PathIsRelative(specifier) && !IsDeclarationFileName(specifier) +}