diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 8a84182c6cbfb..699e902dab5a6 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -342,12 +342,14 @@ export interface PackageJsonPathFields { imports?: object; exports?: object; name?: string; + dependencies?: MapLike; + peerDependencies?: MapLike; + optionalDependencies?: MapLike; } interface PackageJson extends PackageJsonPathFields { name?: string; version?: string; - peerDependencies?: MapLike; } function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index df7e2fb5d8cc7..cf3eeca0488f8 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -11,6 +11,7 @@ import { comparePaths, Comparison, CompilerOptions, + concatenate, containsIgnoredPath, containsPath, createGetCanonicalFileName, @@ -48,6 +49,7 @@ import { getOwnKeys, getPackageJsonTypesVersionsPaths, getPackageNameFromTypesPackageName, + getPackageScopeForPath, getPathsBasePath, getRelativePathFromDirectory, getRelativePathToDirectoryOrUrl, @@ -55,6 +57,7 @@ import { getResolvePackageJsonImports, getSourceFileOfModule, getSupportedExtensions, + getTemporaryModuleResolutionState, getTextOfIdentifierOrLiteral, hasJSFileExtension, hasTSFileExtension, @@ -84,6 +87,7 @@ import { ModuleDeclaration, ModuleKind, ModulePath, + ModuleResolutionHost, ModuleResolutionKind, ModuleSpecifierCache, ModuleSpecifierEnding, @@ -92,6 +96,7 @@ import { NodeFlags, NodeModulePathParts, normalizePath, + PackageJsonPathFields, pathContainsNodeModules, pathIsBareSpecifier, pathIsRelative, @@ -102,6 +107,7 @@ import { removeTrailingDirectorySeparator, replaceFirstStar, ResolutionMode, + resolveModuleName, resolvePath, ScriptKind, shouldAllowImportingTsExtension, @@ -254,7 +260,7 @@ export function getNodeModulesPackageName( options: ModuleSpecifierOptions = {}, ): string | undefined { const info = getInfo(importingSourceFile.fileName, host); - const modulePaths = getAllModulePaths(info, nodeModulesFileName, host, preferences, options); + const modulePaths = getAllModulePaths(info, nodeModulesFileName, host, preferences, compilerOptions, options); return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, preferences, /*packageNameOnly*/ true, options.overrideImportMode)); } @@ -269,7 +275,7 @@ function getModuleSpecifierWorker( options: ModuleSpecifierOptions = {}, ): string { const info = getInfo(importingSourceFileName, host); - const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, options); + const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, compilerOptions, options); return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) || getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), preferences); } @@ -361,7 +367,7 @@ export function getModuleSpecifiersWithCacheInfo( if (!moduleSourceFile) return { moduleSpecifiers: emptyArray, computedWithoutCache }; computedWithoutCache = true; - modulePaths ||= getAllModulePathsWorker(getInfo(importingSourceFile.fileName, host), moduleSourceFile.originalFileName, host); + modulePaths ||= getAllModulePathsWorker(getInfo(importingSourceFile.fileName, host), moduleSourceFile.originalFileName, host, compilerOptions, options); const result = computeModuleSpecifiers( modulePaths, compilerOptions, @@ -691,6 +697,7 @@ function getAllModulePaths( importedFileName: string, host: ModuleSpecifierResolutionHost, preferences: UserPreferences, + compilerOptions: CompilerOptions, options: ModuleSpecifierOptions = {}, ) { const importingFilePath = toPath(info.importingSourceFileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)); @@ -700,14 +707,45 @@ function getAllModulePaths( const cached = cache.get(importingFilePath, importedFilePath, preferences, options); if (cached?.modulePaths) return cached.modulePaths; } - const modulePaths = getAllModulePathsWorker(info, importedFileName, host); + const modulePaths = getAllModulePathsWorker(info, importedFileName, host, compilerOptions, options); if (cache) { cache.setModulePaths(importingFilePath, importedFilePath, preferences, options, modulePaths); } return modulePaths; } -function getAllModulePathsWorker(info: Info, importedFileName: string, host: ModuleSpecifierResolutionHost): readonly ModulePath[] { +const runtimeDependencyFields = ["dependencies", "peerDependencies", "optionalDependencies"] as const; + +function getAllRuntimeDependencies(packageJson: PackageJsonPathFields) { + let result; + for (const field of runtimeDependencyFields) { + const deps = packageJson[field]; + if (deps && typeof deps === "object") { + result = concatenate(result, getOwnKeys(deps)); + } + } + return result; +} + +function getAllModulePathsWorker(info: Info, importedFileName: string, host: ModuleSpecifierResolutionHost, compilerOptions: CompilerOptions, options: ModuleSpecifierOptions): readonly ModulePath[] { + const cache = host.getModuleResolutionCache?.(); + const links = host.getSymlinkCache?.(); + if (cache && links && host.readFile && !pathContainsNodeModules(info.importingSourceFileName)) { + Debug.type(host); + // Cache resolutions for all `dependencies` of the `package.json` context of the input file. + // This should populate all the relevant symlinks in the symlink cache, and most, if not all, of these resolutions + // should get (re)used. + const state = getTemporaryModuleResolutionState(cache.getPackageJsonInfoCache(), host, {}); + const packageJson = getPackageScopeForPath(info.importingSourceFileName, state); + if (packageJson) { + const toResolve = getAllRuntimeDependencies(packageJson.contents.packageJsonContent); + for (const depName of (toResolve || emptyArray)) { + const resolved = resolveModuleName(depName, combinePaths(packageJson.packageDirectory, "package.json"), compilerOptions, host, cache, /*redirectedReference*/ undefined, options.overrideImportMode); + links.setSymlinksFromResolution(resolved.resolvedModule); + } + } + } + const allFileNames = new Map(); let importedFileFromNodeModules = false; forEachFileNameOfModule( diff --git a/src/compiler/program.ts b/src/compiler/program.ts index fedc7b39a6fec..886133027b5cb 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2698,12 +2698,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg // Before falling back to the host return host.fileExists(f); }, + realpath: maybeBind(host, host.realpath), useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(), getBuildInfo: () => program.getBuildInfo?.(), getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref), redirectTargetsMap, getFileIncludeReasons: program.getFileIncludeReasons, createHash: maybeBind(host, host.createHash), + getModuleResolutionCache: () => program.getModuleResolutionCache(), + trace: maybeBind(host, host.trace), }; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 010196f5e1c08..fc2316b7eaa81 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -9709,6 +9709,9 @@ export interface ModuleSpecifierResolutionHost { getCommonSourceDirectory(): string; getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode; getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode; + + getModuleResolutionCache?(): ModuleResolutionCache | undefined; + trace?(s: string): void; } /** @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5a53f8199c1f3..3759d3fd21325 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -9080,6 +9080,7 @@ export interface SymlinkCache { ) => void, typeReferenceDirectives: ModeAwareCache, ): void; + setSymlinksFromResolution(resolution: ResolvedModuleFull | undefined): void; /** * @internal * Whether `setSymlinksFromResolutions` has already been called. @@ -9119,6 +9120,9 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic typeReferenceDirectives.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective)); }, hasProcessedResolutions: () => hasProcessedResolutions, + setSymlinksFromResolution(resolution) { + processResolution(this, resolution); + }, hasAnySymlinks, }; diff --git a/src/testRunner/unittests/tsc/moduleResolution.ts b/src/testRunner/unittests/tsc/moduleResolution.ts index aee945ede1868..4eb42bf26225f 100644 --- a/src/testRunner/unittests/tsc/moduleResolution.ts +++ b/src/testRunner/unittests/tsc/moduleResolution.ts @@ -213,4 +213,62 @@ describe("unittests:: tsc:: moduleResolution::", () => { }, { currentDirectory: "/home/src/projects/component-type-checker/packages/app" }), commandLineArgs: ["--traceResolution", "--explainFiles"], }); + + verifyTscWatch({ + scenario: "moduleResolution", + subScenario: "late discovered dependency symlink", + sys: () => + createWatchedSystem({ + "/workspace/packageA/index.d.ts": dedent` + export declare class Foo { + private f: any; + }`, + "/workspace/packageB/package.json": dedent` + { + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } + }`, + "/workspace/packageB/index.d.ts": dedent` + import { Foo } from "package-a"; + export declare function invoke(): Foo;`, + "/workspace/packageC/package.json": dedent` + { + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } + }`, + "/workspace/packageC/index.ts": dedent` + import * as pkg from "package-b"; + + export const a = pkg.invoke();`, + "/workspace/packageC/node_modules/package-a": { symLink: "/workspace/packageA" }, + "/workspace/packageB/node_modules/package-a": { symLink: "/workspace/packageA" }, + "/workspace/packageC/node_modules/package-b": { symLink: "/workspace/packageB" }, + "/a/lib/lib.d.ts": libContent, + "/workspace/packageC/tsconfig.json": jsonToReadableText({ + compilerOptions: { + declaration: true, + }, + }), + }, { currentDirectory: "/workspace/packageC" }), + commandLineArgs: ["--traceResolution", "--explainFiles", "--watch"], + edits: [ + { + caption: "change index.ts", + edit: fs => + fs.writeFile( + "/workspace/packageC/index.ts", + dedent` + import * as pkg from "package-b"; + + export const aa = pkg.invoke();`, + ), + timeouts: sys => sys.runQueuedTimeoutCallbacks(), + }, + ], + }); }); diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.js b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.js new file mode 100644 index 0000000000000..3b1693123f427 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.js @@ -0,0 +1,74 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts] //// + +//// [foo.d.ts] +export declare class Foo { + private f: any; +} +//// [index.d.ts] +import { Foo } from "./foo.js"; +export function create(): Foo; +//// [package.json] +{ + "name": "package-a", + "version": "0.0.1", + "exports": { + ".": "./index.js", + "./cls": "./foo.js" + } +} +//// [package.json] +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +//// [index.d.ts] +import { create } from "package-a"; +export declare function invoke(): ReturnType; +//// [package.json] +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } +} +//// [index.ts] +import * as pkg from "package-b"; + +export const a = pkg.invoke(); + +//// [index.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +const pkg = __importStar(require("package-b")); +exports.a = pkg.invoke(); + + +//// [index.d.ts] +export declare const a: import("package-a/cls").Foo; diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.symbols b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.symbols new file mode 100644 index 0000000000000..54b0997e16c25 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.symbols @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts] //// + +=== workspace/packageA/foo.d.ts === +export declare class Foo { +>Foo : Symbol(Foo, Decl(foo.d.ts, 0, 0)) + + private f: any; +>f : Symbol(Foo.f, Decl(foo.d.ts, 0, 26)) +} +=== workspace/packageA/index.d.ts === +import { Foo } from "./foo.js"; +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +export function create(): Foo; +>create : Symbol(create, Decl(index.d.ts, 0, 31)) +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +=== workspace/packageB/index.d.ts === +import { create } from "package-a"; +>create : Symbol(create, Decl(index.d.ts, 0, 8)) + +export declare function invoke(): ReturnType; +>invoke : Symbol(invoke, Decl(index.d.ts, 0, 35)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>create : Symbol(create, Decl(index.d.ts, 0, 8)) + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const a = pkg.invoke(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>pkg.invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 35)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 35)) + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.types b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.types new file mode 100644 index 0000000000000..1bd751cb42549 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.types @@ -0,0 +1,47 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts] //// + +=== workspace/packageA/foo.d.ts === +export declare class Foo { +>Foo : Foo +> : ^^^ + + private f: any; +>f : any +} +=== workspace/packageA/index.d.ts === +import { Foo } from "./foo.js"; +>Foo : typeof Foo +> : ^^^^^^^^^^ + +export function create(): Foo; +>create : () => Foo +> : ^^^^^^ + +=== workspace/packageB/index.d.ts === +import { create } from "package-a"; +>create : () => import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +export declare function invoke(): ReturnType; +>invoke : () => ReturnType +> : ^^^^^^ +>create : () => import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : typeof pkg +> : ^^^^^^^^^^ + +export const a = pkg.invoke(); +>a : import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke() : import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke : () => import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg : typeof pkg +> : ^^^^^^^^^^ +>invoke : () => import("workspace/packageA/foo").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.js b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.js new file mode 100644 index 0000000000000..bcc9d95977dc5 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.js @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts] //// + +//// [index.d.ts] +export declare class Foo { + private f: any; +} +//// [package.json] +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +//// [index.d.ts] +import { Foo } from "package-a"; +export declare function invoke(): Foo; +//// [package.json] +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } +} +//// [index.ts] +import * as pkg from "package-b"; + +export const a = pkg.invoke(); + +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +var pkg = require("package-b"); +exports.a = pkg.invoke(); + + +//// [index.d.ts] +export declare const a: import("package-a").Foo; diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.symbols b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.symbols new file mode 100644 index 0000000000000..14e6e5278d67c --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.symbols @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 0)) + + private f: any; +>f : Symbol(Foo.f, Decl(index.d.ts, 0, 26)) +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +export declare function invoke(): Foo; +>invoke : Symbol(invoke, Decl(index.d.ts, 0, 32)) +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const a = pkg.invoke(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>pkg.invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.types b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.types new file mode 100644 index 0000000000000..fe2c175a8f2db --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.types @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Foo +> : ^^^ + + private f: any; +>f : any +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : typeof Foo +> : ^^^^^^^^^^ + +export declare function invoke(): Foo; +>invoke : () => Foo +> : ^^^^^^ + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : typeof pkg +> : ^^^^^^^^^^ + +export const a = pkg.invoke(); +>a : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke() : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg : typeof pkg +> : ^^^^^^^^^^ +>invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.js b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.js new file mode 100644 index 0000000000000..43b73b8609b8b --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.js @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts] //// + +//// [index.d.ts] +export declare class Foo { + private f: any; +} +//// [package.json] +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +//// [index.d.ts] +import { Foo } from "package-a"; +export declare function invoke(): Foo; +//// [package.json] +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB" + }, + "optionalDependencies": { + "package-a": "file:../packageA" + } +} +//// [index.ts] +import * as pkg from "package-b"; + +export const a = pkg.invoke(); + +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +var pkg = require("package-b"); +exports.a = pkg.invoke(); + + +//// [index.d.ts] +export declare const a: import("package-a").Foo; diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.symbols b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.symbols new file mode 100644 index 0000000000000..9a6be68cc544b --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.symbols @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 0)) + + private f: any; +>f : Symbol(Foo.f, Decl(index.d.ts, 0, 26)) +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +export declare function invoke(): Foo; +>invoke : Symbol(invoke, Decl(index.d.ts, 0, 32)) +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const a = pkg.invoke(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>pkg.invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.types b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.types new file mode 100644 index 0000000000000..7482ca3c99bb6 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.types @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Foo +> : ^^^ + + private f: any; +>f : any +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : typeof Foo +> : ^^^^^^^^^^ + +export declare function invoke(): Foo; +>invoke : () => Foo +> : ^^^^^^ + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : typeof pkg +> : ^^^^^^^^^^ + +export const a = pkg.invoke(); +>a : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke() : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg : typeof pkg +> : ^^^^^^^^^^ +>invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.js b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.js new file mode 100644 index 0000000000000..bfeee1d566342 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.js @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts] //// + +//// [index.d.ts] +export declare class Foo { + private f: any; +} +//// [package.json] +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +//// [index.d.ts] +import { Foo } from "package-a"; +export declare function invoke(): Foo; +//// [package.json] +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB" + }, + "peerDependencies": { + "package-a": "file:../packageA" + } +} +//// [index.ts] +import * as pkg from "package-b"; + +export const a = pkg.invoke(); + +//// [index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +var pkg = require("package-b"); +exports.a = pkg.invoke(); + + +//// [index.d.ts] +export declare const a: import("package-a").Foo; diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.symbols b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.symbols new file mode 100644 index 0000000000000..06cb475267274 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.symbols @@ -0,0 +1,27 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 0)) + + private f: any; +>f : Symbol(Foo.f, Decl(index.d.ts, 0, 26)) +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +export declare function invoke(): Foo; +>invoke : Symbol(invoke, Decl(index.d.ts, 0, 32)) +>Foo : Symbol(Foo, Decl(index.d.ts, 0, 8)) + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) + +export const a = pkg.invoke(); +>a : Symbol(a, Decl(index.ts, 2, 12)) +>pkg.invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) +>pkg : Symbol(pkg, Decl(index.ts, 0, 6)) +>invoke : Symbol(pkg.invoke, Decl(index.d.ts, 0, 32)) + diff --git a/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.types b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.types new file mode 100644 index 0000000000000..b7ed0b56f06e1 --- /dev/null +++ b/tests/baselines/reference/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.types @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts] //// + +=== workspace/packageA/index.d.ts === +export declare class Foo { +>Foo : Foo +> : ^^^ + + private f: any; +>f : any +} +=== workspace/packageB/index.d.ts === +import { Foo } from "package-a"; +>Foo : typeof Foo +> : ^^^^^^^^^^ + +export declare function invoke(): Foo; +>invoke : () => Foo +> : ^^^^^^ + +=== workspace/packageC/index.ts === +import * as pkg from "package-b"; +>pkg : typeof pkg +> : ^^^^^^^^^^ + +export const a = pkg.invoke(); +>a : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke() : import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg.invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>pkg : typeof pkg +> : ^^^^^^^^^^ +>invoke : () => import("workspace/packageA/index").Foo +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/tscWatch/moduleResolution/late-discovered-dependency-symlink.js b/tests/baselines/reference/tscWatch/moduleResolution/late-discovered-dependency-symlink.js new file mode 100644 index 0000000000000..9e3b48e86622f --- /dev/null +++ b/tests/baselines/reference/tscWatch/moduleResolution/late-discovered-dependency-symlink.js @@ -0,0 +1,298 @@ +currentDirectory:: /workspace/packageC useCaseSensitiveFileNames: false +Input:: +//// [/workspace/packageA/index.d.ts] +export declare class Foo { + private f: any; +} + +//// [/workspace/packageB/package.json] +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} + +//// [/workspace/packageB/index.d.ts] +import { Foo } from "package-a"; +export declare function invoke(): Foo; + +//// [/workspace/packageC/package.json] +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } +} + +//// [/workspace/packageC/index.ts] +import * as pkg from "package-b"; + +export const a = pkg.invoke(); + +//// [/workspace/packageC/node_modules/package-a] symlink(/workspace/packageA) +//// [/workspace/packageB/node_modules/package-a] symlink(/workspace/packageA) +//// [/workspace/packageC/node_modules/package-b] symlink(/workspace/packageB) +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + +//// [/workspace/packageC/tsconfig.json] +{ + "compilerOptions": { + "declaration": true + } +} + + +/a/lib/tsc.js --traceResolution --explainFiles --watch +Output:: +>> Screen clear +[HH:MM:SS AM] Starting compilation in watch mode... + +Found 'package.json' at '/workspace/packageC/package.json'. +======== Resolving module 'package-b' from '/workspace/packageC/index.ts'. ======== +Module resolution kind is not specified, using 'Node10'. +Loading module 'package-b' from 'node_modules' folder, target file types: TypeScript, Declaration. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +Found 'package.json' at '/workspace/packageC/node_modules/package-b/package.json'. +File '/workspace/packageC/node_modules/package-b.ts' does not exist. +File '/workspace/packageC/node_modules/package-b.tsx' does not exist. +File '/workspace/packageC/node_modules/package-b.d.ts' does not exist. +'package.json' does not have a 'typesVersions' field. +'package.json' does not have a 'typings' field. +'package.json' does not have a 'types' field. +'package.json' does not have a 'main' field. +File '/workspace/packageC/node_modules/package-b/index.ts' does not exist. +File '/workspace/packageC/node_modules/package-b/index.tsx' does not exist. +File '/workspace/packageC/node_modules/package-b/index.d.ts' exists - use it as a name resolution result. +Resolving real path for '/workspace/packageC/node_modules/package-b/index.d.ts', result '/workspace/packageB/index.d.ts'. +======== Module name 'package-b' was successfully resolved to '/workspace/packageB/index.d.ts'. ======== +Found 'package.json' at '/workspace/packageB/package.json'. +======== Resolving module 'package-a' from '/workspace/packageB/index.d.ts'. ======== +Module resolution kind is not specified, using 'Node10'. +Loading module 'package-a' from 'node_modules' folder, target file types: TypeScript, Declaration. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +File '/workspace/packageB/node_modules/package-a/package.json' does not exist. +File '/workspace/packageB/node_modules/package-a.ts' does not exist. +File '/workspace/packageB/node_modules/package-a.tsx' does not exist. +File '/workspace/packageB/node_modules/package-a.d.ts' does not exist. +File '/workspace/packageB/node_modules/package-a/index.ts' does not exist. +File '/workspace/packageB/node_modules/package-a/index.tsx' does not exist. +File '/workspace/packageB/node_modules/package-a/index.d.ts' exists - use it as a name resolution result. +Resolving real path for '/workspace/packageB/node_modules/package-a/index.d.ts', result '/workspace/packageA/index.d.ts'. +======== Module name 'package-a' was successfully resolved to '/workspace/packageA/index.d.ts'. ======== +File '/workspace/packageA/package.json' does not exist. +File '/workspace/package.json' does not exist. +File '/package.json' does not exist. +File '/a/lib/package.json' does not exist. +File '/a/package.json' does not exist. +File '/package.json' does not exist according to earlier cached lookups. +======== Resolving module 'package-b' from '/workspace/packageC/package.json'. ======== +Resolution for module 'package-b' was found in cache from location '/workspace/packageC'. +======== Module name 'package-b' was successfully resolved to '/workspace/packageB/index.d.ts'. ======== +======== Resolving module 'package-a' from '/workspace/packageC/package.json'. ======== +Module resolution kind is not specified, using 'Node10'. +Loading module 'package-a' from 'node_modules' folder, target file types: TypeScript, Declaration. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +File '/workspace/packageC/node_modules/package-a/package.json' does not exist. +File '/workspace/packageC/node_modules/package-a.ts' does not exist. +File '/workspace/packageC/node_modules/package-a.tsx' does not exist. +File '/workspace/packageC/node_modules/package-a.d.ts' does not exist. +File '/workspace/packageC/node_modules/package-a/index.ts' does not exist. +File '/workspace/packageC/node_modules/package-a/index.tsx' does not exist. +File '/workspace/packageC/node_modules/package-a/index.d.ts' exists - use it as a name resolution result. +Resolving real path for '/workspace/packageC/node_modules/package-a/index.d.ts', result '/workspace/packageA/index.d.ts'. +======== Module name 'package-a' was successfully resolved to '/workspace/packageA/index.d.ts'. ======== +../../a/lib/lib.d.ts + Default library for target 'es5' +../packageA/index.d.ts + Imported via "package-a" from file '../packageB/index.d.ts' +../packageB/index.d.ts + Imported via "package-b" from file 'index.ts' +index.ts + Matched by default include pattern '**/*' +[HH:MM:SS AM] Found 0 errors. Watching for file changes. + + + +//// [/workspace/packageC/index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.a = void 0; +var pkg = require("package-b"); +exports.a = pkg.invoke(); + + +//// [/workspace/packageC/index.d.ts] +export declare const a: import("package-a").Foo; + + + +FsWatches:: +/a/lib/lib.d.ts: *new* + {} +/workspace/packageA/index.d.ts: *new* + {} +/workspace/packageB/index.d.ts: *new* + {} +/workspace/packageC/index.ts: *new* + {} +/workspace/packageC/tsconfig.json: *new* + {} + +FsWatchesRecursive:: +/workspace/packageC: *new* + {} + +Program root files: [ + "/workspace/packageC/index.ts" +] +Program options: { + "declaration": true, + "traceResolution": true, + "explainFiles": true, + "watch": true, + "configFilePath": "/workspace/packageC/tsconfig.json" +} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/workspace/packageA/index.d.ts +/workspace/packageB/index.d.ts +/workspace/packageC/index.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/workspace/packageA/index.d.ts +/workspace/packageB/index.d.ts +/workspace/packageC/index.ts + +Shape signatures in builder refreshed for:: +/a/lib/lib.d.ts (used version) +/workspace/packagea/index.d.ts (used version) +/workspace/packageb/index.d.ts (used version) +/workspace/packagec/index.ts (computed .d.ts during emit) + +exitCode:: ExitStatus.undefined + +Change:: change index.ts + +Input:: +//// [/workspace/packageC/index.ts] +import * as pkg from "package-b"; + +export const aa = pkg.invoke(); + + +Timeout callback:: count: 1 +1: timerToUpdateProgram *new* + +Before running Timeout callback:: count: 1 +1: timerToUpdateProgram + +After running Timeout callback:: count: 0 +Output:: +>> Screen clear +[HH:MM:SS AM] File change detected. Starting incremental compilation... + +File '/a/lib/package.json' does not exist according to earlier cached lookups. +File '/a/package.json' does not exist according to earlier cached lookups. +File '/package.json' does not exist according to earlier cached lookups. +File '/workspace/packageA/package.json' does not exist according to earlier cached lookups. +File '/workspace/package.json' does not exist according to earlier cached lookups. +File '/package.json' does not exist according to earlier cached lookups. +File '/workspace/packageB/package.json' exists according to earlier cached lookups. +File '/workspace/packageC/package.json' exists according to earlier cached lookups. +Reusing resolution of module 'package-b' from '/workspace/packageC/index.ts' of old program, it was successfully resolved to '/workspace/packageB/index.d.ts'. +======== Resolving module 'package-b' from '/workspace/packageC/package.json'. ======== +Module resolution kind is not specified, using 'Node10'. +Loading module 'package-b' from 'node_modules' folder, target file types: TypeScript, Declaration. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +File '/workspace/packageC/node_modules/package-b/package.json' exists according to earlier cached lookups. +File '/workspace/packageC/node_modules/package-b.ts' does not exist. +File '/workspace/packageC/node_modules/package-b.tsx' does not exist. +File '/workspace/packageC/node_modules/package-b.d.ts' does not exist. +'package.json' does not have a 'typings' field. +'package.json' does not have a 'types' field. +'package.json' does not have a 'main' field. +File '/workspace/packageC/node_modules/package-b/index.ts' does not exist. +File '/workspace/packageC/node_modules/package-b/index.tsx' does not exist. +File '/workspace/packageC/node_modules/package-b/index.d.ts' exists - use it as a name resolution result. +Resolving real path for '/workspace/packageC/node_modules/package-b/index.d.ts', result '/workspace/packageB/index.d.ts'. +======== Module name 'package-b' was successfully resolved to '/workspace/packageB/index.d.ts'. ======== +======== Resolving module 'package-a' from '/workspace/packageC/package.json'. ======== +Module resolution kind is not specified, using 'Node10'. +Loading module 'package-a' from 'node_modules' folder, target file types: TypeScript, Declaration. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +File '/workspace/packageC/node_modules/package-a/package.json' does not exist. +File '/workspace/packageC/node_modules/package-a.ts' does not exist. +File '/workspace/packageC/node_modules/package-a.tsx' does not exist. +File '/workspace/packageC/node_modules/package-a.d.ts' does not exist. +File '/workspace/packageC/node_modules/package-a/index.ts' does not exist. +File '/workspace/packageC/node_modules/package-a/index.tsx' does not exist. +File '/workspace/packageC/node_modules/package-a/index.d.ts' exists - use it as a name resolution result. +Resolving real path for '/workspace/packageC/node_modules/package-a/index.d.ts', result '/workspace/packageA/index.d.ts'. +======== Module name 'package-a' was successfully resolved to '/workspace/packageA/index.d.ts'. ======== +../../a/lib/lib.d.ts + Default library for target 'es5' +../packageA/index.d.ts + Imported via "package-a" from file '../packageB/index.d.ts' +../packageB/index.d.ts + Imported via "package-b" from file 'index.ts' +index.ts + Matched by default include pattern '**/*' +[HH:MM:SS AM] Found 0 errors. Watching for file changes. + + + +//// [/workspace/packageC/index.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.aa = void 0; +var pkg = require("package-b"); +exports.aa = pkg.invoke(); + + +//// [/workspace/packageC/index.d.ts] +export declare const aa: import("package-a").Foo; + + + + +Program root files: [ + "/workspace/packageC/index.ts" +] +Program options: { + "declaration": true, + "traceResolution": true, + "explainFiles": true, + "watch": true, + "configFilePath": "/workspace/packageC/tsconfig.json" +} +Program structureReused: Completely +Program files:: +/a/lib/lib.d.ts +/workspace/packageA/index.d.ts +/workspace/packageB/index.d.ts +/workspace/packageC/index.ts + +Semantic diagnostics in builder refreshed for:: +/workspace/packageC/index.ts + +Shape signatures in builder refreshed for:: +/workspace/packagec/index.ts (computed .d.ts) + +exitCode:: ExitStatus.undefined diff --git a/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts new file mode 100644 index 0000000000000..603ba5af12f31 --- /dev/null +++ b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesDeepNonrelativeName.ts @@ -0,0 +1,43 @@ +// @declaration: true +// @module: nodenext +// @filename: workspace/packageA/foo.d.ts +export declare class Foo { + private f: any; +} +// @filename: workspace/packageA/index.d.ts +import { Foo } from "./foo.js"; +export function create(): Foo; +// @filename: workspace/packageA/package.json +{ + "name": "package-a", + "version": "0.0.1", + "exports": { + ".": "./index.js", + "./cls": "./foo.js" + } +} +// @filename: workspace/packageB/package.json +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageB/index.d.ts +import { create } from "package-a"; +export declare function invoke(): ReturnType; +// @filename: workspace/packageC/package.json +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageC/index.ts +import * as pkg from "package-b"; + +export const a = pkg.invoke(); +// @link: workspace/packageA -> workspace/packageC/node_modules/package-a +// @link: workspace/packageA -> workspace/packageB/node_modules/package-a +// @link: workspace/packageB -> workspace/packageC/node_modules/package-b \ No newline at end of file diff --git a/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts new file mode 100644 index 0000000000000..96eb125ab150f --- /dev/null +++ b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkGeneratesNonrelativeName.ts @@ -0,0 +1,30 @@ +// @declaration: true +// @filename: workspace/packageA/index.d.ts +export declare class Foo { + private f: any; +} +// @filename: workspace/packageB/package.json +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageB/index.d.ts +import { Foo } from "package-a"; +export declare function invoke(): Foo; +// @filename: workspace/packageC/package.json +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB", + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageC/index.ts +import * as pkg from "package-b"; + +export const a = pkg.invoke(); +// @link: workspace/packageA -> workspace/packageC/node_modules/package-a +// @link: workspace/packageA -> workspace/packageB/node_modules/package-a +// @link: workspace/packageB -> workspace/packageC/node_modules/package-b \ No newline at end of file diff --git a/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts new file mode 100644 index 0000000000000..c5e97afb459d9 --- /dev/null +++ b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkOptionalGeneratesNonrelativeName.ts @@ -0,0 +1,32 @@ +// @declaration: true +// @filename: workspace/packageA/index.d.ts +export declare class Foo { + private f: any; +} +// @filename: workspace/packageB/package.json +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageB/index.d.ts +import { Foo } from "package-a"; +export declare function invoke(): Foo; +// @filename: workspace/packageC/package.json +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB" + }, + "optionalDependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageC/index.ts +import * as pkg from "package-b"; + +export const a = pkg.invoke(); +// @link: workspace/packageA -> workspace/packageC/node_modules/package-a +// @link: workspace/packageA -> workspace/packageB/node_modules/package-a +// @link: workspace/packageB -> workspace/packageC/node_modules/package-b \ No newline at end of file diff --git a/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts new file mode 100644 index 0000000000000..94a56e3adde30 --- /dev/null +++ b/tests/cases/compiler/symlinkedWorkspaceDependenciesNoDirectLinkPeerGeneratesNonrelativeName.ts @@ -0,0 +1,32 @@ +// @declaration: true +// @filename: workspace/packageA/index.d.ts +export declare class Foo { + private f: any; +} +// @filename: workspace/packageB/package.json +{ + "private": true, + "dependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageB/index.d.ts +import { Foo } from "package-a"; +export declare function invoke(): Foo; +// @filename: workspace/packageC/package.json +{ + "private": true, + "dependencies": { + "package-b": "file:../packageB" + }, + "peerDependencies": { + "package-a": "file:../packageA" + } +} +// @filename: workspace/packageC/index.ts +import * as pkg from "package-b"; + +export const a = pkg.invoke(); +// @link: workspace/packageA -> workspace/packageC/node_modules/package-a +// @link: workspace/packageA -> workspace/packageB/node_modules/package-a +// @link: workspace/packageB -> workspace/packageC/node_modules/package-b \ No newline at end of file