Skip to content

Commit

Permalink
🤖 Pick PR #49360 (Expose import mode calculation func...) into releas…
Browse files Browse the repository at this point in the history
…e-4.7 (#49370)

* Cherry-pick PR #49360 into release-4.7

Component commits:
5eb6425 Expose import mode calculation functions

1f907ae Make `SourceFileImportsList` internal again.

4e40185 Accepted API baselines.

* Fix lints.

Co-authored-by: Daniel Rosenwasser <drosen@microsoft.com>
Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 3, 2022
1 parent 3ce08c6 commit 4c4c803
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 8 deletions.
43 changes: 35 additions & 8 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,20 +533,39 @@ namespace ts {
return resolutions;
}

/* @internal */
interface SourceFileImportsList {
imports: SourceFile["imports"];
moduleAugmentations: SourceFile["moduleAugmentations"];
/**
* Subset of a SourceFile used to calculate index-based resolutions
* This includes some internal fields, so unless you have very good reason,
* (and are willing to use some less stable internals) you should probably just pass a SourceFile.
*
* @internal
*/
export interface SourceFileImportsList {
/* @internal */ imports: SourceFile["imports"];
/* @internal */ moduleAugmentations: SourceFile["moduleAugmentations"];
impliedNodeFormat?: SourceFile["impliedNodeFormat"];
};

/* @internal */
/**
* Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly
* provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file.
*/
export function getModeForFileReference(ref: FileReference | string, containingFileMode: SourceFile["impliedNodeFormat"]) {
return (isString(ref) ? containingFileMode : ref.resolutionMode) || containingFileMode;
}

/* @internal */
export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number) {
/**
* Calculates the final resolution mode for an import at some index within a file's imports list. This is generally the explicitly
* defined mode of the import if provided, or, if not, the mode of the containing file (with some exceptions: import=require is always commonjs, dynamic import is always esm).
* If you have an actual import node, prefer using getModeForUsageLocation on the reference string node.
* @param file File to fetch the resolution mode within
* @param index Index into the file's complete resolution list to get the resolution of - this is a concatenation of the file's imports and module augmentations
*/
export function getModeForResolutionAtIndex(file: SourceFile, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
/** @internal */
// eslint-disable-next-line @typescript-eslint/unified-signatures
export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined {
if (file.impliedNodeFormat === undefined) return undefined;
// we ensure all elements of file.imports and file.moduleAugmentations have the relevant parent pointers set during program setup,
// so it's safe to use them even pre-bind
Expand All @@ -564,7 +583,15 @@ namespace ts {
return false;
}

/* @internal */
/**
* Calculates the final resolution mode for a given module reference node. This is generally the explicitly provided resolution mode, if
* one exists, or the mode of the containing source file. (Excepting import=require, which is always commonjs, and dynamic import, which is always esm).
* Notably, this function always returns `undefined` if the containing file has an `undefined` `impliedNodeFormat` - this field is only set when
* `moduleResolution` is `node16`+.
* @param file The file the import or import-like reference is contained within
* @param usage The module reference string
* @returns The final resolution mode of the import
*/
export function getModeForUsageLocation(file: {impliedNodeFormat?: SourceFile["impliedNodeFormat"]}, usage: StringLiteralLike) {
if (file.impliedNodeFormat === undefined) return undefined;
if ((isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent))) {
Expand Down
25 changes: 25 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5099,6 +5099,31 @@ declare namespace ts {
export function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string;
export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string;
export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent?: number): string;
/**
* Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly
* provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file.
*/
export function getModeForFileReference(ref: FileReference | string, containingFileMode: SourceFile["impliedNodeFormat"]): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
/**
* Calculates the final resolution mode for an import at some index within a file's imports list. This is generally the explicitly
* defined mode of the import if provided, or, if not, the mode of the containing file (with some exceptions: import=require is always commonjs, dynamic import is always esm).
* If you have an actual import node, prefer using getModeForUsageLocation on the reference string node.
* @param file File to fetch the resolution mode within
* @param index Index into the file's complete resolution list to get the resolution of - this is a concatenation of the file's imports and module augmentations
*/
export function getModeForResolutionAtIndex(file: SourceFile, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
/**
* Calculates the final resolution mode for a given module reference node. This is generally the explicitly provided resolution mode, if
* one exists, or the mode of the containing source file. (Excepting import=require, which is always commonjs, and dynamic import, which is always esm).
* Notably, this function always returns `undefined` if the containing file has an `undefined` `impliedNodeFormat` - this field is only set when
* `moduleResolution` is `node16`+.
* @param file The file the import or import-like reference is contained within
* @param usage The module reference string
* @returns The final resolution mode of the import
*/
export function getModeForUsageLocation(file: {
impliedNodeFormat?: SourceFile["impliedNodeFormat"];
}, usage: StringLiteralLike): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[];
/**
* A function for determining if a given file is esm or cjs format, assuming modern node module resolution rules, as configured by the
Expand Down
25 changes: 25 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5099,6 +5099,31 @@ declare namespace ts {
export function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string;
export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string;
export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent?: number): string;
/**
* Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly
* provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file.
*/
export function getModeForFileReference(ref: FileReference | string, containingFileMode: SourceFile["impliedNodeFormat"]): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
/**
* Calculates the final resolution mode for an import at some index within a file's imports list. This is generally the explicitly
* defined mode of the import if provided, or, if not, the mode of the containing file (with some exceptions: import=require is always commonjs, dynamic import is always esm).
* If you have an actual import node, prefer using getModeForUsageLocation on the reference string node.
* @param file File to fetch the resolution mode within
* @param index Index into the file's complete resolution list to get the resolution of - this is a concatenation of the file's imports and module augmentations
*/
export function getModeForResolutionAtIndex(file: SourceFile, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
/**
* Calculates the final resolution mode for a given module reference node. This is generally the explicitly provided resolution mode, if
* one exists, or the mode of the containing source file. (Excepting import=require, which is always commonjs, and dynamic import, which is always esm).
* Notably, this function always returns `undefined` if the containing file has an `undefined` `impliedNodeFormat` - this field is only set when
* `moduleResolution` is `node16`+.
* @param file The file the import or import-like reference is contained within
* @param usage The module reference string
* @returns The final resolution mode of the import
*/
export function getModeForUsageLocation(file: {
impliedNodeFormat?: SourceFile["impliedNodeFormat"];
}, usage: StringLiteralLike): ModuleKind.CommonJS | ModuleKind.ESNext | undefined;
export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[];
/**
* A function for determining if a given file is esm or cjs format, assuming modern node module resolution rules, as configured by the
Expand Down

0 comments on commit 4c4c803

Please sign in to comment.