Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ export interface PackageJsonPathFields {
imports?: object;
exports?: object;
name?: string;
dependencies?: object;
}

interface PackageJson extends PackageJsonPathFields {
Expand Down
27 changes: 27 additions & 0 deletions src/compiler/moduleSpecifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ import {
getOwnKeys,
getPackageJsonTypesVersionsPaths,
getPackageNameFromTypesPackageName,
getPackageScopeForPath,
getPathsBasePath,
getRelativePathFromDirectory,
getRelativePathToDirectoryOrUrl,
getResolvePackageJsonExports,
getResolvePackageJsonImports,
getSourceFileOfModule,
getSupportedExtensions,
getTemporaryModuleResolutionState,
getTextOfIdentifierOrLiteral,
hasJSFileExtension,
hasTSFileExtension,
Expand Down Expand Up @@ -84,6 +86,7 @@ import {
ModuleDeclaration,
ModuleKind,
ModulePath,
ModuleResolutionHost,
ModuleResolutionKind,
ModuleSpecifierCache,
ModuleSpecifierEnding,
Expand All @@ -102,6 +105,7 @@ import {
removeTrailingDirectorySeparator,
replaceFirstStar,
ResolutionMode,
resolveModuleName,
resolvePath,
ScriptKind,
shouldAllowImportingTsExtension,
Expand Down Expand Up @@ -708,6 +712,29 @@ function getAllModulePaths(
}

function getAllModulePathsWorker(info: Info, importedFileName: string, host: ModuleSpecifierResolutionHost): 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 deps = packageJson.contents.packageJsonContent.dependencies;
weswigham marked this conversation as resolved.
Show resolved Hide resolved
if (deps && typeof deps === "object") {
const toResolve = getOwnKeys(deps as MapLike<unknown>);
for (const depName of toResolve) {
const cached = cache.getOrCreateCacheForNonRelativeName(depName, /*mode*/ undefined, /*redirectedReference*/ undefined).get(info.canonicalSourceDirectory);
weswigham marked this conversation as resolved.
Show resolved Hide resolved
if (cached) continue;
const resolved = resolveModuleName(depName, info.importingSourceFileName, {}, host, cache);
weswigham marked this conversation as resolved.
Show resolved Hide resolved
links.setSymlinksFromResolution(resolved.resolvedModule);
}
}
}
}

const allFileNames = new Map<string, { path: string; isRedirect: boolean; isInNodeModules: boolean; }>();
let importedFileFromNodeModules = false;
forEachFileNameOfModule(
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2698,12 +2698,14 @@ 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(),
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9706,6 +9706,8 @@ export interface ModuleSpecifierResolutionHost {
getCommonSourceDirectory(): string;
getDefaultResolutionModeForFile(sourceFile: SourceFile): ResolutionMode;
getModeForResolutionAtIndex(file: SourceFile, index: number): ResolutionMode;

getModuleResolutionCache?(): ModuleResolutionCache | undefined;
}

/** @internal */
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9079,6 +9079,7 @@ export interface SymlinkCache {
) => void,
typeReferenceDirectives: ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>,
): void;
setSymlinksFromResolution(resolution: ResolvedModuleFull | undefined): void;
/**
* @internal
* Whether `setSymlinksFromResolutions` has already been called.
Expand Down Expand Up @@ -9118,6 +9119,9 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic
typeReferenceDirectives.forEach(resolution => processResolution(this, resolution.resolvedTypeReferenceDirective));
},
hasProcessedResolutions: () => hasProcessedResolutions,
setSymlinksFromResolution(resolution) {
processResolution(this, resolution);
},
};

function processResolution(cache: SymlinkCache, resolution: ResolvedModuleFull | ResolvedTypeReferenceDirective | undefined) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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))

Original file line number Diff line number Diff line change
@@ -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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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))

Original file line number Diff line number Diff line change
@@ -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
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Loading