Merge pull request #26564 from Microsoft/fix26497

Emit lib reference directives in declaration output
This commit is contained in:
Ron Buckton 2018-08-21 09:48:07 -07:00 committed by GitHub
commit 42c9208fd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 167 additions and 11 deletions

View file

@ -140,7 +140,7 @@ function diagnosticFromJson(json, host) {
category: json.category,
code: json.code,
source: json.source,
relatedInformation: json.relatedInformation && json.relatedInformation.map(diagnosticRelatedInformationFromJson, host)
relatedInformation: json.relatedInformation && json.relatedInformation.map(json => diagnosticRelatedInformationFromJson(json, host))
});
}
exports.diagnosticFromJson = diagnosticFromJson;
@ -169,7 +169,9 @@ function diagnosticRelatedInformationFromJson(json, host) {
file: json.file && sourceFileFromJson(json.file, host),
start: json.start,
length: json.length,
messageText: json.messageText
messageText: json.messageText,
category: json.category,
code: json.code
};
}
exports.diagnosticRelatedInformationFromJson = diagnosticRelatedInformationFromJson;

View file

@ -2593,14 +2593,14 @@ namespace ts {
}
function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) {
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || []);
emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || [], node.syntheticLibReferences || []);
}
function emitTripleSlashDirectivesIfNeeded(node: SourceFile) {
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives);
if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives, node.libReferenceDirectives);
}
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>) {
function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray<FileReference>, types: ReadonlyArray<FileReference>, libs: ReadonlyArray<FileReference>) {
if (hasNoDefaultLib) {
write(`/// <reference no-default-lib="true"/>`);
writeLine();
@ -2628,6 +2628,10 @@ namespace ts {
write(`/// <reference types="${directive.fileName}" />`);
writeLine();
}
for (const directive of libs) {
write(`/// <reference lib="${directive.fileName}" />`);
writeLine();
}
}
function emitSourceFileWorker(node: SourceFile) {

View file

@ -1237,6 +1237,7 @@ namespace ts {
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
getLibFileFromReference: program.getLibFileFromReference,
isSourceFileFromExternalLibrary,
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),

View file

@ -33,7 +33,7 @@ namespace ts {
let needsScopeFixMarker = false;
let resultHasScopeMarker = false;
let enclosingDeclaration: Node;
let necessaryTypeRefernces: Map<true> | undefined;
let necessaryTypeReferences: Map<true> | undefined;
let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
let lateStatementReplacementMap: Map<VisitResult<LateVisibilityPaintedStatement>>;
let suppressNewDiagnosticContexts: boolean;
@ -53,6 +53,7 @@ namespace ts {
let currentSourceFile: SourceFile;
let refs: Map<SourceFile>;
let libs: Map<boolean>;
const resolver = context.getEmitResolver();
const options = context.getCompilerOptions();
const newLine = getNewLineCharacter(options);
@ -63,9 +64,9 @@ namespace ts {
if (!typeReferenceDirectives) {
return;
}
necessaryTypeRefernces = necessaryTypeRefernces || createMap<true>();
necessaryTypeReferences = necessaryTypeReferences || createMap<true>();
for (const ref of typeReferenceDirectives) {
necessaryTypeRefernces.set(ref, true);
necessaryTypeReferences.set(ref, true);
}
}
@ -163,6 +164,7 @@ namespace ts {
if (node.kind === SyntaxKind.Bundle) {
isBundledEmit = true;
refs = createMap<SourceFile>();
libs = createMap<boolean>();
let hasNoDefaultLib = false;
const bundle = createBundle(map(node.sourceFiles,
sourceFile => {
@ -177,6 +179,7 @@ namespace ts {
needsScopeFixMarker = false;
resultHasScopeMarker = false;
collectReferences(sourceFile, refs);
collectLibs(sourceFile, libs);
if (isExternalModule(sourceFile)) {
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
needsDeclare = false;
@ -200,6 +203,7 @@ namespace ts {
}));
bundle.syntheticFileReferences = [];
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
bundle.syntheticLibReferences = getLibReferences();
bundle.hasNoDefaultLib = hasNoDefaultLib;
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath);
@ -219,8 +223,9 @@ namespace ts {
suppressNewDiagnosticContexts = false;
lateMarkedStatements = undefined;
lateStatementReplacementMap = createMap();
necessaryTypeRefernces = undefined;
necessaryTypeReferences = undefined;
refs = collectReferences(currentSourceFile, createMap());
libs = collectLibs(currentSourceFile, createMap());
const references: FileReference[] = [];
const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
@ -231,12 +236,16 @@ namespace ts {
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements);
}
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib);
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
return updated;
function getLibReferences() {
return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 }));
}
function getFileReferencesForUsedTypeReferences() {
return necessaryTypeRefernces ? mapDefined(arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : [];
return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForTypeName) : [];
}
function getFileReferenceForTypeName(typeName: string): FileReference | undefined {
@ -297,6 +306,16 @@ namespace ts {
return ret;
}
function collectLibs(sourceFile: SourceFile, ret: Map<boolean>) {
forEach(sourceFile.libReferenceDirectives, ref => {
const lib = host.getLibFileFromReference(ref);
if (lib) {
ret.set(ref.fileName.toLocaleLowerCase(), true);
}
});
return ret;
}
function filterBindingPatternInitializers(name: BindingName) {
if (name.kind === SyntaxKind.Identifier) {
return name;

View file

@ -2648,6 +2648,7 @@ namespace ts {
sourceFiles: ReadonlyArray<SourceFile>;
/* @internal */ syntheticFileReferences?: ReadonlyArray<FileReference>;
/* @internal */ syntheticTypeReferences?: ReadonlyArray<FileReference>;
/* @internal */ syntheticLibReferences?: ReadonlyArray<FileReference>;
/* @internal */ hasNoDefaultLib?: boolean;
}
@ -5074,6 +5075,7 @@ namespace ts {
/* @internal */
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
getCommonSourceDirectory(): string;
getCanonicalFileName(fileName: string): string;

View file

@ -0,0 +1,25 @@
//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts] ////
//// [file1.ts]
/// <reference lib="dom" />
export declare const elem: HTMLElement;
//// [file2.ts]
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
//// [file1.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//// [file2.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//// [file1.d.ts]
/// <reference lib="dom" />
export declare const elem: HTMLElement;
//// [file2.d.ts]
/// <reference lib="dom" />
export {};

View file

@ -0,0 +1,13 @@
=== tests/cases/conformance/declarationEmit/file1.ts ===
/// <reference lib="dom" />
export declare const elem: HTMLElement;
>elem : Symbol(elem, Decl(file1.ts, 1, 20))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
=== tests/cases/conformance/declarationEmit/file2.ts ===
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
>elem : Symbol(elem, Decl(file2.ts, 2, 13))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

View file

@ -0,0 +1,11 @@
=== tests/cases/conformance/declarationEmit/file1.ts ===
/// <reference lib="dom" />
export declare const elem: HTMLElement;
>elem : HTMLElement
=== tests/cases/conformance/declarationEmit/file2.ts ===
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
>elem : HTMLElement

View file

@ -0,0 +1,30 @@
//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts] ////
//// [file1.ts]
/// <reference lib="dom" />
export declare const elem: HTMLElement;
//// [file2.ts]
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
//// [bundle.js]
define("file1", ["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
});
define("file2", ["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
});
//// [bundle.d.ts]
/// <reference lib="dom" />
declare module "file1" {
export const elem: HTMLElement;
}
declare module "file2" {
export {};
}

View file

@ -0,0 +1,13 @@
=== tests/cases/conformance/declarationEmit/file1.ts ===
/// <reference lib="dom" />
export declare const elem: HTMLElement;
>elem : Symbol(elem, Decl(file1.ts, 1, 20))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
=== tests/cases/conformance/declarationEmit/file2.ts ===
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
>elem : Symbol(elem, Decl(file2.ts, 2, 13))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

View file

@ -0,0 +1,11 @@
=== tests/cases/conformance/declarationEmit/file1.ts ===
/// <reference lib="dom" />
export declare const elem: HTMLElement;
>elem : HTMLElement
=== tests/cases/conformance/declarationEmit/file2.ts ===
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;
>elem : HTMLElement

View file

@ -0,0 +1,12 @@
// @target: esnext
// @module: commonjs
// @lib: esnext
// @declaration: true
// @filename: file1.ts
/// <reference lib="dom" />
export declare const elem: HTMLElement;
// @filename: file2.ts
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;

View file

@ -0,0 +1,13 @@
// @target: esnext
// @module: amd
// @lib: esnext
// @declaration: true
// @outFile: bundle.js
// @filename: file1.ts
/// <reference lib="dom" />
export declare const elem: HTMLElement;
// @filename: file2.ts
/// <reference lib="dom" />
export {}
declare const elem: HTMLElement;