Check nearest package.json dependencies for possible package names for specifier candidates (#58176)

This commit is contained in:
Wesley Wigham 2024-04-18 17:43:08 -07:00 committed by GitHub
parent e33b8d9b85
commit 48870169dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 1016 additions and 6 deletions

View File

@ -342,12 +342,14 @@ export interface PackageJsonPathFields {
imports?: object;
exports?: object;
name?: string;
dependencies?: MapLike<string>;
peerDependencies?: MapLike<string>;
optionalDependencies?: MapLike<string>;
}
interface PackageJson extends PackageJsonPathFields {
name?: string;
version?: string;
peerDependencies?: MapLike<string>;
}
function readPackageJsonField<K extends MatchingKeys<PackageJson, string | undefined>>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined;

View File

@ -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<ModuleResolutionHost>(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<string, { path: string; isRedirect: boolean; isInNodeModules: boolean; }>();
let importedFileFromNodeModules = false;
forEachFileNameOfModule(

View File

@ -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),
};
}

View File

@ -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 */

View File

@ -9080,6 +9080,7 @@ export interface SymlinkCache {
) => void,
typeReferenceDirectives: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>,
): 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,
};

View File

@ -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(),
},
],
});
});

View File

@ -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<typeof create>;
//// [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;

View File

@ -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<typeof create>;
>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))

View File

@ -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<typeof create>;
>invoke : () => ReturnType<typeof create>
> : ^^^^^^
>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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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;

View File

@ -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))

View File

@ -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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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;

View File

@ -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))

View File

@ -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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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;

View File

@ -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))

View File

@ -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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
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

View File

@ -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<typeof create>;
// @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

View File

@ -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

View File

@ -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

View File

@ -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