diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index cdddd048e42..c44a8c2f760 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -948,9 +948,14 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!); const importMode = overrideMode || importingSourceFile.impliedNodeFormat; if (getResolvePackageJsonExports(options)) { + // The package name that we found in node_modules could be different from the package + // name in the package.json content via url/filepath dependency specifiers. We need to + // use the actual directory name, so don't look at `packageJsonContent.name` here. + const nodeModulesDirectoryName = packageRootPath.substring(parts.topLevelPackageNameIndex + 1); + const packageName = getPackageNameFromTypesPackageName(nodeModulesDirectoryName); const conditions = getConditions(options, importMode === ModuleKind.ESNext); - const fromExports = packageJsonContent.exports && typeof packageJsonContent.name === "string" - ? tryGetModuleNameFromExports(options, path, packageRootPath, getPackageNameFromTypesPackageName(packageJsonContent.name), packageJsonContent.exports, conditions) + const fromExports = packageJsonContent.exports + ? tryGetModuleNameFromExports(options, path, packageRootPath, packageName, packageJsonContent.exports, conditions) : undefined; if (fromExports) { const withJsExtension = !hasTSFileExtension(fromExports.moduleFileToTry) diff --git a/tests/baselines/reference/tsbuild/moduleSpecifiers/synthesized-module-specifiers-across-projects-resolve-correctly.js b/tests/baselines/reference/tsbuild/moduleSpecifiers/synthesized-module-specifiers-across-projects-resolve-correctly.js index c245a8f92eb..491da2a1d21 100644 --- a/tests/baselines/reference/tsbuild/moduleSpecifiers/synthesized-module-specifiers-across-projects-resolve-correctly.js +++ b/tests/baselines/reference/tsbuild/moduleSpecifiers/synthesized-module-specifiers-across-projects-resolve-correctly.js @@ -190,7 +190,7 @@ export const LASSIE_CONFIG = { name: 'Lassie' }; //// [/src/src-dogs/lassie/lassiedog.d.ts] import { Dog } from '../dog.js'; export declare class LassieDog extends Dog { - protected static getDogConfig: () => import("../index.js").DogConfig; + protected static getDogConfig: () => import("src-types").DogConfig; } @@ -204,7 +204,7 @@ export { LassieDog }; //// [/src/src-dogs/tsconfig.tsbuildinfo] -{"program":{"fileNames":["../../lib/lib.es2022.full.d.ts","../src-types/dogconfig.d.ts","../src-types/index.d.ts","./dogconfig.ts","./dog.ts","./lassie/lassieconfig.ts","./lassie/lassiedog.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true,"impliedFormat":1},{"version":"-3612551765-export interface DogConfig {\n name: string;\n}\n","impliedFormat":99},{"version":"-6677489680-export * from './dogconfig.js';\n","impliedFormat":99},{"version":"1966273863-import { DogConfig } from 'src-types';\n\nexport const DOG_CONFIG: DogConfig = {\n name: 'Default dog',\n};\n","signature":"15679103984-import { DogConfig } from 'src-types';\nexport declare const DOG_CONFIG: DogConfig;\n","impliedFormat":99},{"version":"6091345804-import { DogConfig } from 'src-types';\nimport { DOG_CONFIG } from './dogconfig.js';\n\nexport abstract class Dog {\n\n public static getCapabilities(): DogConfig {\n return DOG_CONFIG;\n }\n}\n","signature":"26984075437-import { DogConfig } from 'src-types';\nexport declare abstract class Dog {\n static getCapabilities(): DogConfig;\n}\n","impliedFormat":99},{"version":"4440579024-import { DogConfig } from 'src-types';\n\nexport const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };\n","signature":"17379560247-import { DogConfig } from 'src-types';\nexport declare const LASSIE_CONFIG: DogConfig;\n","impliedFormat":99},{"version":"-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n","signature":"-19295250986-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"../index.js\").DogConfig;\n}\n","impliedFormat":99},{"version":"-15974991320-export * from 'src-types';\nexport * from './lassie/lassiedog.js';\n","impliedFormat":99}],"root":[[4,8]],"options":{"composite":true,"declaration":true,"module":100},"fileIdsList":[[3,4],[3],[3,7],[5,6],[2],[5,8]],"referencedMap":[[5,1],[4,2],[8,3],[6,2],[7,4],[3,5]],"exportedModulesMap":[[5,2],[4,2],[8,3],[6,2],[7,6],[3,5]],"semanticDiagnosticsPerFile":[1,5,4,8,6,7,2,3],"latestChangedDtsFile":"./index.d.ts"},"version":"FakeTSVersion"} +{"program":{"fileNames":["../../lib/lib.es2022.full.d.ts","../src-types/dogconfig.d.ts","../src-types/index.d.ts","./dogconfig.ts","./dog.ts","./lassie/lassieconfig.ts","./lassie/lassiedog.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true,"impliedFormat":1},{"version":"-3612551765-export interface DogConfig {\n name: string;\n}\n","impliedFormat":99},{"version":"-6677489680-export * from './dogconfig.js';\n","impliedFormat":99},{"version":"1966273863-import { DogConfig } from 'src-types';\n\nexport const DOG_CONFIG: DogConfig = {\n name: 'Default dog',\n};\n","signature":"15679103984-import { DogConfig } from 'src-types';\nexport declare const DOG_CONFIG: DogConfig;\n","impliedFormat":99},{"version":"6091345804-import { DogConfig } from 'src-types';\nimport { DOG_CONFIG } from './dogconfig.js';\n\nexport abstract class Dog {\n\n public static getCapabilities(): DogConfig {\n return DOG_CONFIG;\n }\n}\n","signature":"26984075437-import { DogConfig } from 'src-types';\nexport declare abstract class Dog {\n static getCapabilities(): DogConfig;\n}\n","impliedFormat":99},{"version":"4440579024-import { DogConfig } from 'src-types';\n\nexport const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };\n","signature":"17379560247-import { DogConfig } from 'src-types';\nexport declare const LASSIE_CONFIG: DogConfig;\n","impliedFormat":99},{"version":"-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n","signature":"-10239718190-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"src-types\").DogConfig;\n}\n","impliedFormat":99},{"version":"-15974991320-export * from 'src-types';\nexport * from './lassie/lassiedog.js';\n","impliedFormat":99}],"root":[[4,8]],"options":{"composite":true,"declaration":true,"module":100},"fileIdsList":[[3,4],[3],[3,7],[5,6],[2],[3,5]],"referencedMap":[[5,1],[4,2],[8,3],[6,2],[7,4],[3,5]],"exportedModulesMap":[[5,2],[4,2],[8,3],[6,2],[7,6],[3,5]],"semanticDiagnosticsPerFile":[1,5,4,8,6,7,2,3],"latestChangedDtsFile":"./index.d.ts"},"version":"FakeTSVersion"} //// [/src/src-dogs/tsconfig.tsbuildinfo.readable.baseline.txt] { @@ -239,8 +239,8 @@ export { LassieDog }; "../src-types/dogconfig.d.ts" ], [ - "./dog.ts", - "./index.ts" + "../src-types/index.d.ts", + "./dog.ts" ] ], "fileInfos": { @@ -306,11 +306,11 @@ export { LassieDog }; "./lassie/lassiedog.ts": { "original": { "version": "-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n", - "signature": "-19295250986-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"../index.js\").DogConfig;\n}\n", + "signature": "-10239718190-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"src-types\").DogConfig;\n}\n", "impliedFormat": 99 }, "version": "-32303727812-import { Dog } from '../dog.js';\nimport { LASSIE_CONFIG } from './lassieconfig.js';\n\nexport class LassieDog extends Dog {\n protected static getDogConfig = () => LASSIE_CONFIG;\n}\n", - "signature": "-19295250986-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"../index.js\").DogConfig;\n}\n", + "signature": "-10239718190-import { Dog } from '../dog.js';\nexport declare class LassieDog extends Dog {\n protected static getDogConfig: () => import(\"src-types\").DogConfig;\n}\n", "impliedFormat": "esnext" }, "./index.ts": { @@ -381,8 +381,8 @@ export { LassieDog }; "../src-types/index.d.ts" ], "./lassie/lassiedog.ts": [ - "./dog.ts", - "./index.ts" + "../src-types/index.d.ts", + "./dog.ts" ], "../src-types/index.d.ts": [ "../src-types/dogconfig.d.ts" @@ -401,7 +401,7 @@ export { LassieDog }; "latestChangedDtsFile": "./index.d.ts" }, "version": "FakeTSVersion", - "size": 2634 + "size": 2632 } //// [/src/src-types/dogconfig.d.ts] diff --git a/tests/cases/fourslash/server/autoImportNodeModuleSymlinkRenamed.ts b/tests/cases/fourslash/server/autoImportNodeModuleSymlinkRenamed.ts new file mode 100644 index 00000000000..dad5dd599ea --- /dev/null +++ b/tests/cases/fourslash/server/autoImportNodeModuleSymlinkRenamed.ts @@ -0,0 +1,63 @@ +/// + +// @Filename: /package.json +//// { +//// "name": "monorepo", +//// "workspaces": ["packages/*"] +//// } + +// @Filename: /packages/utils/package.json +//// { +//// "name": "utils", +//// "version": "1.0.0", +//// "exports": "./dist/index.js" +//// } + +// @Filename: /packages/utils/tsconfig.json +//// { +//// "compilerOptions": { +//// "composite": true, +//// "module": "nodenext", +//// "rootDir": "src", +//// "outDir": "dist" +//// }, +//// "include": ["src"] +//// } + +// @Filename: /packages/utils/src/index.ts +//// export function gainUtility() { return 0; } + +// @Filename: /packages/web/package.json +//// { +//// "name": "web", +//// "version": "1.0.0", +//// "dependencies": { +//// "@monorepo/utils": "file:../utils" +//// } +//// } + +// @Filename: /packages/web/tsconfig.json +//// { +//// "compilerOptions": { +//// "composite": true, +//// "module": "esnext", +//// "moduleResolution": "bundler", +//// "rootDir": "src", +//// "outDir": "dist", +//// "emitDeclarationOnly": true +//// }, +//// "include": ["src"], +//// "references": [ +//// { "path": "../utils" } +//// ] +//// } + +// @Filename: /packages/web/src/index.ts +//// gainUtility/**/ + +// @link: /packages/utils -> /node_modules/utils +// @link: /packages/utils -> /node_modules/@monorepo/utils +// @link: /packages/web -> /node_modules/web + +goTo.marker(""); +verify.importFixModuleSpecifiers("", ["@monorepo/utils"]);