Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/compiler/moduleSpecifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
ExportAssignment,
Extension,
extensionFromPath,
extensionsNotSupportingExtensionlessResolution,
fileExtensionIsOneOf,
FileIncludeKind,
firstDefined,
Expand Down Expand Up @@ -91,6 +92,7 @@ import {
removeExtension,
removeFileExtension,
removeSuffix,
removeTrailingDirectorySeparator,
ResolutionMode,
resolvePath,
ScriptKind,
Expand Down Expand Up @@ -1007,10 +1009,24 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
// happens very easily in fourslash tests though, since every test file listed gets included. See
// importNameCodeFix_typesVersions.ts for an example.)
const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(moduleFileToTry))) {
const canonicalModuleFileToTry = getCanonicalFileName(moduleFileToTry);
if (removeFileExtension(mainExportFile) === removeFileExtension(canonicalModuleFileToTry)) {
// ^ An arbitrary removal of file extension for this comparison is almost certainly wrong
return { packageRootPath, moduleFileToTry };
}
else if (
packageJsonContent.type !== "module" &&
!fileExtensionIsOneOf(canonicalModuleFileToTry, extensionsNotSupportingExtensionlessResolution) &&
startsWith(canonicalModuleFileToTry, mainExportFile) &&
getDirectoryPath(canonicalModuleFileToTry) === removeTrailingDirectorySeparator(mainExportFile) &&
removeFileExtension(getBaseFileName(canonicalModuleFileToTry)) === "index"
) {
// if mainExportFile is a directory, which contains moduleFileToTry, we just try index file
// example mainExportFile: `pkg/lib` and moduleFileToTry: `pkg/lib/index`, we can use packageRootPath
// but this behavior is deprecated for packages with "type": "module", so we only do this for packages without "type": "module"
// and make sure that the extension on index.{???} is something that supports omitting the extension
return { packageRootPath, moduleFileToTry };
}
}
}
else {
Expand Down
26 changes: 26 additions & 0 deletions tests/cases/fourslash/autoImportPackageRootPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference path="fourslash.ts" />

// @allowJs: true

// @Filename: /node_modules/pkg/package.json
//// {
//// "name": "pkg",
//// "version": "1.0.0",
//// "main": "lib",
//// "module": "lib"
//// }

// @Filename: /node_modules/pkg/lib/index.js
//// export function foo() {};

// @Filename: /package.json
//// {
//// "dependencies": {
//// "pkg": "*"
//// }
//// }

// @Filename: /index.ts
//// foo/**/

verify.importFixModuleSpecifiers("", ["pkg"]);
25 changes: 25 additions & 0 deletions tests/cases/fourslash/autoImportPackageRootPathExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/// <reference path="fourslash.ts" />

// @allowJs: true

// @Filename: /node_modules/pkg/package.json
//// {
//// "name": "pkg",
//// "version": "1.0.0",
//// "main": "lib"
//// }

// @Filename: /node_modules/pkg/lib/index.d.mts
//// export declare function foo(): any;

// @Filename: /package.json
//// {
//// "dependencies": {
//// "pkg": "*"
//// }
//// }

// @Filename: /index.ts
//// foo/**/

verify.importFixModuleSpecifiers("", ["pkg/lib/index.mjs"]);
26 changes: 26 additions & 0 deletions tests/cases/fourslash/autoImportPackageRootPathTypeModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference path="fourslash.ts" />

// @allowJs: true

// @Filename: /node_modules/pkg/package.json
//// {
//// "name": "pkg",
//// "version": "1.0.0",
//// "main": "lib",
//// "type": "module"
//// }

// @Filename: /node_modules/pkg/lib/index.js
//// export function foo() {};

// @Filename: /package.json
//// {
//// "dependencies": {
//// "pkg": "*"
//// }
//// }

// @Filename: /index.ts
//// foo/**/

verify.importFixModuleSpecifiers("", ["pkg/lib"]);