Skip to content

Commit 42c9208

Browse files
authored
Merge pull request #26564 from Microsoft/fix26497
Emit lib reference directives in declaration output
2 parents 103f894 + 1de8cd3 commit 42c9208

13 files changed

+167
-11
lines changed

scripts/build/gulp-typescript-oop/protocol.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function diagnosticFromJson(json, host) {
140140
category: json.category,
141141
code: json.code,
142142
source: json.source,
143-
relatedInformation: json.relatedInformation && json.relatedInformation.map(diagnosticRelatedInformationFromJson, host)
143+
relatedInformation: json.relatedInformation && json.relatedInformation.map(json => diagnosticRelatedInformationFromJson(json, host))
144144
});
145145
}
146146
exports.diagnosticFromJson = diagnosticFromJson;
@@ -169,7 +169,9 @@ function diagnosticRelatedInformationFromJson(json, host) {
169169
file: json.file && sourceFileFromJson(json.file, host),
170170
start: json.start,
171171
length: json.length,
172-
messageText: json.messageText
172+
messageText: json.messageText,
173+
category: json.category,
174+
code: json.code
173175
};
174176
}
175177
exports.diagnosticRelatedInformationFromJson = diagnosticRelatedInformationFromJson;

src/compiler/emitter.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2593,14 +2593,14 @@ namespace ts {
25932593
}
25942594

25952595
function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) {
2596-
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []);
2596+
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || [], node.syntheticLibReferences || []);
25972597
}
25982598

25992599
function emitTripleSlashDirectivesIfNeeded(node: SourceFile) {
2600-
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives);
2600+
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives, node.libReferenceDirectives);
26012601
}
26022602

2603-
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>) {
2603+
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>, libs: ReadonlyArray<FileReference>) {
26042604
if (hasNoDefaultLib) {
26052605
write(`/// <reference no-default-lib="true"/>`);
26062606
writeLine();
@@ -2628,6 +2628,10 @@ namespace ts {
26282628
write(`/// <reference types="${directive.fileName}" />`);
26292629
writeLine();
26302630
}
2631+
for (const directive of libs) {
2632+
write(`/// <reference lib="${directive.fileName}" />`);
2633+
writeLine();
2634+
}
26312635
}
26322636

26332637
function emitSourceFileWorker(node: SourceFile) {

src/compiler/program.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,7 @@ namespace ts {
12371237
getSourceFile: program.getSourceFile,
12381238
getSourceFileByPath: program.getSourceFileByPath,
12391239
getSourceFiles: program.getSourceFiles,
1240+
getLibFileFromReference: program.getLibFileFromReference,
12401241
isSourceFileFromExternalLibrary,
12411242
writeFile: writeFileCallback || (
12421243
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),

src/compiler/transformers/declarations.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace ts {
3333
let needsScopeFixMarker = false;
3434
let resultHasScopeMarker = false;
3535
let enclosingDeclaration: Node;
36-
let necessaryTypeRefernces: Map<true> | undefined;
36+
let necessaryTypeReferences: Map<true> | undefined;
3737
let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
3838
let lateStatementReplacementMap: Map<VisitResult<LateVisibilityPaintedStatement>>;
3939
let suppressNewDiagnosticContexts: boolean;
@@ -53,6 +53,7 @@ namespace ts {
5353

5454
let currentSourceFile: SourceFile;
5555
let refs: Map<SourceFile>;
56+
let libs: Map<boolean>;
5657
const resolver = context.getEmitResolver();
5758
const options = context.getCompilerOptions();
5859
const newLine = getNewLineCharacter(options);
@@ -63,9 +64,9 @@ namespace ts {
6364
if (!typeReferenceDirectives) {
6465
return;
6566
}
66-
necessaryTypeRefernces = necessaryTypeRefernces || createMap<true>();
67+
necessaryTypeReferences = necessaryTypeReferences || createMap<true>();
6768
for (const ref of typeReferenceDirectives) {
68-
necessaryTypeRefernces.set(ref, true);
69+
necessaryTypeReferences.set(ref, true);
6970
}
7071
}
7172

@@ -163,6 +164,7 @@ namespace ts {
163164
if (node.kind === SyntaxKind.Bundle) {
164165
isBundledEmit = true;
165166
refs = createMap<SourceFile>();
167+
libs = createMap<boolean>();
166168
let hasNoDefaultLib = false;
167169
const bundle = createBundle(map(node.sourceFiles,
168170
sourceFile => {
@@ -177,6 +179,7 @@ namespace ts {
177179
needsScopeFixMarker = false;
178180
resultHasScopeMarker = false;
179181
collectReferences(sourceFile, refs);
182+
collectLibs(sourceFile, libs);
180183
if (isExternalModule(sourceFile)) {
181184
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
182185
needsDeclare = false;
@@ -200,6 +203,7 @@ namespace ts {
200203
}));
201204
bundle.syntheticFileReferences = [];
202205
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
206+
bundle.syntheticLibReferences = getLibReferences();
203207
bundle.hasNoDefaultLib = hasNoDefaultLib;
204208
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
205209
const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath);
@@ -219,8 +223,9 @@ namespace ts {
219223
suppressNewDiagnosticContexts = false;
220224
lateMarkedStatements = undefined;
221225
lateStatementReplacementMap = createMap();
222-
necessaryTypeRefernces = undefined;
226+
necessaryTypeReferences = undefined;
223227
refs = collectReferences(currentSourceFile, createMap());
228+
libs = collectLibs(currentSourceFile, createMap());
224229
const references: FileReference[] = [];
225230
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
226231
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
@@ -231,12 +236,16 @@ namespace ts {
231236
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
232237
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements);
233238
}
234-
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib);
239+
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
235240
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
236241
return updated;
237242

243+
function getLibReferences() {
244+
return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 }));
245+
}
246+
238247
function getFileReferencesForUsedTypeReferences() {
239-
return necessaryTypeRefernces ? mapDefined(arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : [];
248+
return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForTypeName) : [];
240249
}
241250

242251
function getFileReferenceForTypeName(typeName: string): FileReference | undefined {
@@ -297,6 +306,16 @@ namespace ts {
297306
return ret;
298307
}
299308

309+
function collectLibs(sourceFile: SourceFile, ret: Map<boolean>) {
310+
forEach(sourceFile.libReferenceDirectives, ref => {
311+
const lib = host.getLibFileFromReference(ref);
312+
if (lib) {
313+
ret.set(ref.fileName.toLocaleLowerCase(), true);
314+
}
315+
});
316+
return ret;
317+
}
318+
300319
function filterBindingPatternInitializers(name: BindingName) {
301320
if (name.kind === SyntaxKind.Identifier) {
302321
return name;

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,6 +2648,7 @@ namespace ts {
26482648
sourceFiles: ReadonlyArray<SourceFile>;
26492649
/* @internal */ syntheticFileReferences?: ReadonlyArray<FileReference>;
26502650
/* @internal */ syntheticTypeReferences?: ReadonlyArray<FileReference>;
2651+
/* @internal */ syntheticLibReferences?: ReadonlyArray<FileReference>;
26512652
/* @internal */ hasNoDefaultLib?: boolean;
26522653
}
26532654

@@ -5074,6 +5075,7 @@ namespace ts {
50745075

50755076
/* @internal */
50765077
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
5078+
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
50775079

50785080
getCommonSourceDirectory(): string;
50795081
getCanonicalFileName(fileName: string): string;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts] ////
2+
3+
//// [file1.ts]
4+
/// <reference lib="dom" />
5+
export declare const elem: HTMLElement;
6+
7+
//// [file2.ts]
8+
/// <reference lib="dom" />
9+
export {}
10+
declare const elem: HTMLElement;
11+
12+
//// [file1.js]
13+
"use strict";
14+
Object.defineProperty(exports, "__esModule", { value: true });
15+
//// [file2.js]
16+
"use strict";
17+
Object.defineProperty(exports, "__esModule", { value: true });
18+
19+
20+
//// [file1.d.ts]
21+
/// <reference lib="dom" />
22+
export declare const elem: HTMLElement;
23+
//// [file2.d.ts]
24+
/// <reference lib="dom" />
25+
export {};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/declarationEmit/file1.ts ===
2+
/// <reference lib="dom" />
3+
export declare const elem: HTMLElement;
4+
>elem : Symbol(elem, Decl(file1.ts, 1, 20))
5+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
6+
7+
=== tests/cases/conformance/declarationEmit/file2.ts ===
8+
/// <reference lib="dom" />
9+
export {}
10+
declare const elem: HTMLElement;
11+
>elem : Symbol(elem, Decl(file2.ts, 2, 13))
12+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
13+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/conformance/declarationEmit/file1.ts ===
2+
/// <reference lib="dom" />
3+
export declare const elem: HTMLElement;
4+
>elem : HTMLElement
5+
6+
=== tests/cases/conformance/declarationEmit/file2.ts ===
7+
/// <reference lib="dom" />
8+
export {}
9+
declare const elem: HTMLElement;
10+
>elem : HTMLElement
11+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts] ////
2+
3+
//// [file1.ts]
4+
/// <reference lib="dom" />
5+
export declare const elem: HTMLElement;
6+
7+
//// [file2.ts]
8+
/// <reference lib="dom" />
9+
export {}
10+
declare const elem: HTMLElement;
11+
12+
//// [bundle.js]
13+
define("file1", ["require", "exports"], function (require, exports) {
14+
"use strict";
15+
Object.defineProperty(exports, "__esModule", { value: true });
16+
});
17+
define("file2", ["require", "exports"], function (require, exports) {
18+
"use strict";
19+
Object.defineProperty(exports, "__esModule", { value: true });
20+
});
21+
22+
23+
//// [bundle.d.ts]
24+
/// <reference lib="dom" />
25+
declare module "file1" {
26+
export const elem: HTMLElement;
27+
}
28+
declare module "file2" {
29+
export {};
30+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/declarationEmit/file1.ts ===
2+
/// <reference lib="dom" />
3+
export declare const elem: HTMLElement;
4+
>elem : Symbol(elem, Decl(file1.ts, 1, 20))
5+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
6+
7+
=== tests/cases/conformance/declarationEmit/file2.ts ===
8+
/// <reference lib="dom" />
9+
export {}
10+
declare const elem: HTMLElement;
11+
>elem : Symbol(elem, Decl(file2.ts, 2, 13))
12+
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
13+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/conformance/declarationEmit/file1.ts ===
2+
/// <reference lib="dom" />
3+
export declare const elem: HTMLElement;
4+
>elem : HTMLElement
5+
6+
=== tests/cases/conformance/declarationEmit/file2.ts ===
7+
/// <reference lib="dom" />
8+
export {}
9+
declare const elem: HTMLElement;
10+
>elem : HTMLElement
11+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @target: esnext
2+
// @module: commonjs
3+
// @lib: esnext
4+
// @declaration: true
5+
// @filename: file1.ts
6+
/// <reference lib="dom" />
7+
export declare const elem: HTMLElement;
8+
9+
// @filename: file2.ts
10+
/// <reference lib="dom" />
11+
export {}
12+
declare const elem: HTMLElement;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @target: esnext
2+
// @module: amd
3+
// @lib: esnext
4+
// @declaration: true
5+
// @outFile: bundle.js
6+
// @filename: file1.ts
7+
/// <reference lib="dom" />
8+
export declare const elem: HTMLElement;
9+
10+
// @filename: file2.ts
11+
/// <reference lib="dom" />
12+
export {}
13+
declare const elem: HTMLElement;

0 commit comments

Comments
 (0)