Skip to content

Commit 48f2ada

Browse files
authored
Add string literal completions for package.json imports field (microsoft#57718)
1 parent a271797 commit 48f2ada

File tree

67 files changed

+13778
-106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+13778
-106
lines changed

src/compiler/moduleNameResolver.ts

+19-19
Original file line numberDiff line numberDiff line change
@@ -2624,8 +2624,8 @@ function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, s
26242624
mainExport = (scope.contents.packageJsonContent.exports as MapLike<unknown>)["."];
26252625
}
26262626
if (mainExport) {
2627-
const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, subpath, scope, /*isImports*/ false);
2628-
return loadModuleFromTargetImportOrExport(mainExport, "", /*pattern*/ false, ".");
2627+
const loadModuleFromTargetExportOrImport = getLoadModuleFromTargetExportOrImport(extensions, state, cache, redirectedReference, subpath, scope, /*isImports*/ false);
2628+
return loadModuleFromTargetExportOrImport(mainExport, "", /*pattern*/ false, ".");
26292629
}
26302630
}
26312631
else if (allKeysStartWithDot(scope.contents.packageJsonContent.exports as MapLike<unknown>)) {
@@ -2635,7 +2635,7 @@ function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, s
26352635
}
26362636
return toSearchResult(/*value*/ undefined);
26372637
}
2638-
const result = loadModuleFromImportsOrExports(extensions, state, cache, redirectedReference, subpath, scope.contents.packageJsonContent.exports, scope, /*isImports*/ false);
2638+
const result = loadModuleFromExportsOrImports(extensions, state, cache, redirectedReference, subpath, scope.contents.packageJsonContent.exports, scope, /*isImports*/ false);
26392639
if (result) {
26402640
return result;
26412641
}
@@ -2669,7 +2669,7 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc
26692669
return toSearchResult(/*value*/ undefined);
26702670
}
26712671

2672-
const result = loadModuleFromImportsOrExports(extensions, state, cache, redirectedReference, moduleName, scope.contents.packageJsonContent.imports, scope, /*isImports*/ true);
2672+
const result = loadModuleFromExportsOrImports(extensions, state, cache, redirectedReference, moduleName, scope.contents.packageJsonContent.imports, scope, /*isImports*/ true);
26732673
if (result) {
26742674
return result;
26752675
}
@@ -2699,30 +2699,30 @@ export function comparePatternKeys(a: string, b: string): Comparison {
26992699
return Comparison.EqualTo;
27002700
}
27012701

2702-
function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult<Resolved> | undefined {
2703-
const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, moduleName, scope, isImports);
2702+
function loadModuleFromExportsOrImports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult<Resolved> | undefined {
2703+
const loadModuleFromTargetExportOrImport = getLoadModuleFromTargetExportOrImport(extensions, state, cache, redirectedReference, moduleName, scope, isImports);
27042704

27052705
if (!endsWith(moduleName, directorySeparator) && !moduleName.includes("*") && hasProperty(lookupTable, moduleName)) {
2706-
const target = (lookupTable as { [idx: string]: unknown; })[moduleName];
2707-
return loadModuleFromTargetImportOrExport(target, /*subpath*/ "", /*pattern*/ false, moduleName);
2706+
const target = (lookupTable as MapLike<unknown>)[moduleName];
2707+
return loadModuleFromTargetExportOrImport(target, /*subpath*/ "", /*pattern*/ false, moduleName);
27082708
}
27092709
const expandingKeys = toSorted(filter(getOwnKeys(lookupTable as MapLike<unknown>), k => hasOneAsterisk(k) || endsWith(k, "/")), comparePatternKeys);
27102710
for (const potentialTarget of expandingKeys) {
27112711
if (state.features & NodeResolutionFeatures.ExportsPatternTrailers && matchesPatternWithTrailer(potentialTarget, moduleName)) {
2712-
const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget];
2712+
const target = (lookupTable as MapLike<unknown>)[potentialTarget];
27132713
const starPos = potentialTarget.indexOf("*");
27142714
const subpath = moduleName.substring(potentialTarget.substring(0, starPos).length, moduleName.length - (potentialTarget.length - 1 - starPos));
2715-
return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget);
2715+
return loadModuleFromTargetExportOrImport(target, subpath, /*pattern*/ true, potentialTarget);
27162716
}
27172717
else if (endsWith(potentialTarget, "*") && startsWith(moduleName, potentialTarget.substring(0, potentialTarget.length - 1))) {
2718-
const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget];
2718+
const target = (lookupTable as MapLike<unknown>)[potentialTarget];
27192719
const subpath = moduleName.substring(potentialTarget.length - 1);
2720-
return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget);
2720+
return loadModuleFromTargetExportOrImport(target, subpath, /*pattern*/ true, potentialTarget);
27212721
}
27222722
else if (startsWith(moduleName, potentialTarget)) {
2723-
const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget];
2723+
const target = (lookupTable as MapLike<unknown>)[potentialTarget];
27242724
const subpath = moduleName.substring(potentialTarget.length);
2725-
return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ false, potentialTarget);
2725+
return loadModuleFromTargetExportOrImport(target, subpath, /*pattern*/ false, potentialTarget);
27262726
}
27272727
}
27282728

@@ -2742,9 +2742,9 @@ function hasOneAsterisk(patternKey: string): boolean {
27422742
/**
27432743
* Gets the self-recursive function specialized to retrieving the targeted import/export element for the given resolution configuration
27442744
*/
2745-
function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, scope: PackageJsonInfo, isImports: boolean) {
2746-
return loadModuleFromTargetImportOrExport;
2747-
function loadModuleFromTargetImportOrExport(target: unknown, subpath: string, pattern: boolean, key: string): SearchResult<Resolved> | undefined {
2745+
function getLoadModuleFromTargetExportOrImport(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, scope: PackageJsonInfo, isImports: boolean) {
2746+
return loadModuleFromTargetExportOrImport;
2747+
function loadModuleFromTargetExportOrImport(target: unknown, subpath: string, pattern: boolean, key: string): SearchResult<Resolved> | undefined {
27482748
if (typeof target === "string") {
27492749
if (!pattern && subpath.length > 0 && !endsWith(target, "/")) {
27502750
if (state.traceEnabled) {
@@ -2807,7 +2807,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
28072807
if (condition === "default" || state.conditions.includes(condition) || isApplicableVersionedTypesKey(state.conditions, condition)) {
28082808
traceIfEnabled(state, Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition);
28092809
const subTarget = (target as MapLike<unknown>)[condition];
2810-
const result = loadModuleFromTargetImportOrExport(subTarget, subpath, pattern, key);
2810+
const result = loadModuleFromTargetExportOrImport(subTarget, subpath, pattern, key);
28112811
if (result) {
28122812
traceIfEnabled(state, Diagnostics.Resolved_under_condition_0, condition);
28132813
traceIfEnabled(state, Diagnostics.Exiting_conditional_exports);
@@ -2832,7 +2832,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
28322832
return toSearchResult(/*value*/ undefined);
28332833
}
28342834
for (const elem of target) {
2835-
const result = loadModuleFromTargetImportOrExport(elem, subpath, pattern, key);
2835+
const result = loadModuleFromTargetExportOrImport(elem, subpath, pattern, key);
28362836
if (result) {
28372837
return result;
28382838
}

src/compiler/utilities.ts

+17
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ import {
201201
getParseTreeNode,
202202
getPathComponents,
203203
getPathFromPathComponents,
204+
getRelativePathFromDirectory,
204205
getRelativePathToDirectoryOrUrl,
205206
getResolutionModeOverride,
206207
getRootLength,
@@ -498,6 +499,7 @@ import {
498499
ResolvedModuleWithFailedLookupLocations,
499500
ResolvedTypeReferenceDirective,
500501
ResolvedTypeReferenceDirectiveWithFailedLookupLocations,
502+
resolvePath,
501503
returnFalse,
502504
ReturnStatement,
503505
returnUndefined,
@@ -6490,6 +6492,21 @@ export function getPossibleOriginalInputExtensionForExtension(path: string): Ext
64906492
[Extension.Tsx, Extension.Ts, Extension.Jsx, Extension.Js];
64916493
}
64926494

6495+
/** @internal */
6496+
export function getPossibleOriginalInputPathWithoutChangingExt(
6497+
filePath: string,
6498+
ignoreCase: boolean,
6499+
outputDir: string | undefined,
6500+
getCommonSourceDirectory: () => string,
6501+
): string {
6502+
return outputDir ?
6503+
resolvePath(
6504+
getCommonSourceDirectory(),
6505+
getRelativePathFromDirectory(outputDir, filePath, ignoreCase),
6506+
) :
6507+
filePath;
6508+
}
6509+
64936510
/**
64946511
* Returns 'undefined' if and only if 'options.paths' is undefined.
64956512
*

src/harness/vfsUtil.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ export class FileSystem {
11481148
for (const key of Object.keys(files)) {
11491149
const value = normalizeFileSetEntry(files[key]);
11501150
const path = dirname ? vpath.resolve(dirname, key) : key;
1151-
vpath.validate(path, vpath.ValidationFlags.Absolute);
1151+
vpath.validate(path, vpath.ValidationFlags.Absolute | vpath.ValidationFlags.AllowWildcard);
11521152

11531153
// eslint-disable-next-line no-restricted-syntax
11541154
if (value === null || value === undefined || value instanceof Rmdir || value instanceof Unlink) {

0 commit comments

Comments
 (0)