Skip to content

Commit 3fc727b

Browse files
authored
Use import types to refer to declarations in declaration emit (#24071)
* Stand up a simple implementation using import types for exports of modules which are otherwise inaccessible * Ensure references exist to link to modules containing utilized ambient modules * Accept baselines with new import type usage * Fix lint
1 parent 09b9ec4 commit 3fc727b

File tree

77 files changed

+1154
-1637
lines changed

Some content is hidden

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

77 files changed

+1154
-1637
lines changed

src/compiler/checker.ts

Lines changed: 93 additions & 60 deletions
Large diffs are not rendered by default.

src/compiler/transformers/declarations.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,23 @@ namespace ts {
3737
let lateStatementReplacementMap: Map<VisitResult<LateVisibilityPaintedStatement>>;
3838
let suppressNewDiagnosticContexts: boolean;
3939

40+
const host = context.getEmitHost();
4041
const symbolTracker: SymbolTracker = {
4142
trackSymbol,
4243
reportInaccessibleThisError,
4344
reportInaccessibleUniqueSymbolError,
44-
reportPrivateInBaseOfClassExpression
45+
reportPrivateInBaseOfClassExpression,
46+
moduleResolverHost: host,
47+
trackReferencedAmbientModule,
4548
};
4649
let errorNameNode: DeclarationName | undefined;
4750

4851
let currentSourceFile: SourceFile;
52+
let refs: Map<SourceFile>;
4953
const resolver = context.getEmitResolver();
5054
const options = context.getCompilerOptions();
5155
const newLine = getNewLineCharacter(options);
5256
const { noResolve, stripInternal } = options;
53-
const host = context.getEmitHost();
5457
return transformRoot;
5558

5659
function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: string[]): void {
@@ -63,6 +66,11 @@ namespace ts {
6366
}
6467
}
6568

69+
function trackReferencedAmbientModule(node: ModuleDeclaration) {
70+
const container = getSourceFileOfNode(node);
71+
refs.set("" + getOriginalNodeId(container), container);
72+
}
73+
6674
function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) {
6775
if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) {
6876
// Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info
@@ -197,13 +205,13 @@ namespace ts {
197205
lateMarkedStatements = undefined;
198206
lateStatementReplacementMap = createMap();
199207
necessaryTypeRefernces = undefined;
200-
const refs = collectReferences(currentSourceFile, createMap());
208+
refs = collectReferences(currentSourceFile, createMap());
201209
const references: FileReference[] = [];
202210
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath));
203211
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
204-
refs.forEach(referenceVisitor);
205212
const statements = visitNodes(node.statements, visitDeclarationStatements);
206213
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
214+
refs.forEach(referenceVisitor);
207215
const emittedImports = filter(combinedStatements, isAnyImportSyntax);
208216
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
209217
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements);

src/compiler/types.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3093,7 +3093,7 @@ namespace ts {
30933093
WriteArrayAsGenericType = 1 << 1, // Write Array<T> instead T[]
30943094
GenerateNamesForShadowedTypeParams = 1 << 2, // When a type parameter T is shadowing another T, generate a name for it so it can still be referenced
30953095
UseStructuralFallback = 1 << 3, // When an alias cannot be named by its symbol, rather than report an error, fallback to a structural printout if possible
3096-
// empty space
3096+
ForbidIndexedAccessSymbolReferences = 1 << 4, // Forbid references like `I["a"]["b"]` - print `typeof I.a<x>.b<y>` instead
30973097
WriteTypeArgumentsOfSignature = 1 << 5, // Write the type arguments instead of type parameters of the signature
30983098
UseFullyQualifiedType = 1 << 6, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
30993099
UseOnlyExternalAliasing = 1 << 7, // Only use external aliases for a symbol
@@ -5258,6 +5258,13 @@ namespace ts {
52585258
isAtStartOfLine(): boolean;
52595259
}
52605260

5261+
/* @internal */
5262+
export interface ModuleNameResolverHost {
5263+
getCanonicalFileName(f: string): string;
5264+
getCommonSourceDirectory(): string;
5265+
getCurrentDirectory(): string;
5266+
}
5267+
52615268
/** @deprecated See comment on SymbolWriter */
52625269
// Note: this has non-deprecated internal uses.
52635270
export interface SymbolTracker {
@@ -5268,6 +5275,10 @@ namespace ts {
52685275
reportInaccessibleThisError?(): void;
52695276
reportPrivateInBaseOfClassExpression?(propertyName: string): void;
52705277
reportInaccessibleUniqueSymbolError?(): void;
5278+
/* @internal */
5279+
moduleResolverHost?: ModuleNameResolverHost;
5280+
/* @internal */
5281+
trackReferencedAmbientModule?(decl: ModuleDeclaration): void;
52715282
}
52725283

52735284
export interface TextSpan {

src/compiler/utilities.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,11 +2878,11 @@ namespace ts {
28782878
};
28792879
}
28802880

2881-
export function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string {
2882-
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName);
2881+
export function getResolvedExternalModuleName(host: ModuleNameResolverHost, file: SourceFile, referenceFile?: SourceFile): string {
2882+
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName);
28832883
}
28842884

2885-
export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string {
2885+
export function getExternalModuleNameFromDeclaration(host: ModuleNameResolverHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string {
28862886
const file = resolver.getExternalModuleFileFromDeclaration(declaration);
28872887
if (!file || file.isDeclarationFile) {
28882888
return undefined;
@@ -2893,12 +2893,13 @@ namespace ts {
28932893
/**
28942894
* Resolves a local path to a path which is absolute to the base of the emit
28952895
*/
2896-
export function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string {
2896+
export function getExternalModuleNameFromPath(host: ModuleNameResolverHost, fileName: string, referencePath?: string): string {
28972897
const getCanonicalFileName = (f: string) => host.getCanonicalFileName(f);
2898-
const dir = toPath(host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
2898+
const dir = toPath(referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
28992899
const filePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
29002900
const relativePath = getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
2901-
return removeFileExtension(relativePath);
2901+
const extensionless = removeFileExtension(relativePath);
2902+
return referencePath ? ensurePathIsNonModuleName(extensionless) : extensionless;
29022903
}
29032904

29042905
export function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string) {

tests/baselines/reference/amdDeclarationEmitNoExtraDeclare.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
=== tests/cases/compiler/Class.ts ===
22
import { Configurable } from "./Configurable"
3-
>Configurable : <T extends new (...args: any[]) => {}>(base: T) => T
3+
>Configurable : <T extends import("tests/cases/compiler/Configurable").Constructor<{}>>(base: T) => T
44

55
export class HiddenClass {}
66
>HiddenClass : HiddenClass
77

88
export class ActualClass extends Configurable(HiddenClass) {}
99
>ActualClass : ActualClass
1010
>Configurable(HiddenClass) : HiddenClass
11-
>Configurable : <T extends new (...args: any[]) => {}>(base: T) => T
11+
>Configurable : <T extends import("tests/cases/compiler/Configurable").Constructor<{}>>(base: T) => T
1212
>HiddenClass : typeof HiddenClass
1313

1414
=== tests/cases/compiler/Configurable.ts ===

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,7 @@ declare namespace ts {
19001900
WriteArrayAsGenericType = 2,
19011901
GenerateNamesForShadowedTypeParams = 4,
19021902
UseStructuralFallback = 8,
1903+
ForbidIndexedAccessSymbolReferences = 16,
19031904
WriteTypeArgumentsOfSignature = 32,
19041905
UseFullyQualifiedType = 64,
19051906
UseOnlyExternalAliasing = 128,

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,7 @@ declare namespace ts {
19001900
WriteArrayAsGenericType = 2,
19011901
GenerateNamesForShadowedTypeParams = 4,
19021902
UseStructuralFallback = 8,
1903+
ForbidIndexedAccessSymbolReferences = 16,
19031904
WriteTypeArgumentsOfSignature = 32,
19041905
UseFullyQualifiedType = 64,
19051906
UseOnlyExternalAliasing = 128,

tests/baselines/reference/augmentExportEquals5.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ declare module "express" {
1818
function e(): e.Express;
1919
>e : typeof e
2020
>e : any
21-
>Express : Express
21+
>Express : e.Express
2222

2323
namespace e {
2424
>e : typeof e

tests/baselines/reference/declarationEmitAliasFromIndirectFile.js

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,9 @@ exports["default"] = fp.l10ns;
3636

3737
//// [app.d.ts]
3838
declare const _default: {
39-
ar?: {
40-
weekdays: {
41-
shorthand: [string, string, string, string, string, string, string];
42-
longhand: [string, string, string, string, string, string, string];
43-
};
44-
};
45-
bg?: {
46-
weekdays: {
47-
shorthand: [string, string, string, string, string, string, string];
48-
longhand: [string, string, string, string, string, string, string];
49-
};
50-
};
39+
ar?: import("./locale").CustomLocale;
40+
bg?: import("./locale").CustomLocale;
5141
} & {
52-
default: {
53-
weekdays: {
54-
shorthand: [string, string, string, string, string, string, string];
55-
longhand: [string, string, string, string, string, string, string];
56-
};
57-
};
42+
default: import("./locale").Locale;
5843
};
5944
export default _default;

tests/baselines/reference/declarationEmitAliasFromIndirectFile.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const fp = { l10ns: {} } as FlatpickrFn;
6262
>FlatpickrFn : FlatpickrFn
6363

6464
export default fp.l10ns;
65-
>fp.l10ns : { ar?: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; bg?: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; } & { default: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; }
65+
>fp.l10ns : { ar?: import("tests/cases/compiler/locale").CustomLocale; bg?: import("tests/cases/compiler/locale").CustomLocale; } & { default: import("tests/cases/compiler/locale").Locale; }
6666
>fp : FlatpickrFn
67-
>l10ns : { ar?: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; bg?: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; } & { default: { weekdays: { shorthand: [string, string, string, string, string, string, string]; longhand: [string, string, string, string, string, string, string]; }; }; }
67+
>l10ns : { ar?: import("tests/cases/compiler/locale").CustomLocale; bg?: import("tests/cases/compiler/locale").CustomLocale; } & { default: import("tests/cases/compiler/locale").Locale; }
6868

0 commit comments

Comments
 (0)