diff --git a/scripts/build/gulp-typescript-oop/protocol.js b/scripts/build/gulp-typescript-oop/protocol.js index 58e60b058d4..714b94f22a1 100644 --- a/scripts/build/gulp-typescript-oop/protocol.js +++ b/scripts/build/gulp-typescript-oop/protocol.js @@ -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; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index badbfc4fa3f..613fe7f5c84 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -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, types: ReadonlyArray) { + function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: ReadonlyArray, types: ReadonlyArray, libs: ReadonlyArray) { if (hasNoDefaultLib) { write(`/// `); writeLine(); @@ -2628,6 +2628,10 @@ namespace ts { write(`/// `); writeLine(); } + for (const directive of libs) { + write(`/// `); + writeLine(); + } } function emitSourceFileWorker(node: SourceFile) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d52025f5a30..abbc935cf65 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -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)), diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 2fa093128bc..063b5f1cd1d 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -33,7 +33,7 @@ namespace ts { let needsScopeFixMarker = false; let resultHasScopeMarker = false; let enclosingDeclaration: Node; - let necessaryTypeRefernces: Map | undefined; + let necessaryTypeReferences: Map | undefined; let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; let lateStatementReplacementMap: Map>; let suppressNewDiagnosticContexts: boolean; @@ -53,6 +53,7 @@ namespace ts { let currentSourceFile: SourceFile; let refs: Map; + let libs: Map; const resolver = context.getEmitResolver(); const options = context.getCompilerOptions(); const newLine = getNewLineCharacter(options); @@ -63,9 +64,9 @@ namespace ts { if (!typeReferenceDirectives) { return; } - necessaryTypeRefernces = necessaryTypeRefernces || createMap(); + necessaryTypeReferences = necessaryTypeReferences || createMap(); 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(); + libs = createMap(); 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) { + 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; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8696512071d..4330a776d04 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2648,6 +2648,7 @@ namespace ts { sourceFiles: ReadonlyArray; /* @internal */ syntheticFileReferences?: ReadonlyArray; /* @internal */ syntheticTypeReferences?: ReadonlyArray; + /* @internal */ syntheticLibReferences?: ReadonlyArray; /* @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; diff --git a/tests/baselines/reference/libReferenceDeclarationEmit.js b/tests/baselines/reference/libReferenceDeclarationEmit.js new file mode 100644 index 00000000000..83082c3ee98 --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmit.js @@ -0,0 +1,25 @@ +//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts] //// + +//// [file1.ts] +/// +export declare const elem: HTMLElement; + +//// [file2.ts] +/// +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] +/// +export declare const elem: HTMLElement; +//// [file2.d.ts] +/// +export {}; diff --git a/tests/baselines/reference/libReferenceDeclarationEmit.symbols b/tests/baselines/reference/libReferenceDeclarationEmit.symbols new file mode 100644 index 00000000000..3753ee0b80d --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmit.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +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 === +/// +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, --, --)) + diff --git a/tests/baselines/reference/libReferenceDeclarationEmit.types b/tests/baselines/reference/libReferenceDeclarationEmit.types new file mode 100644 index 00000000000..34102b07321 --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmit.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare const elem: HTMLElement; +>elem : HTMLElement + +=== tests/cases/conformance/declarationEmit/file2.ts === +/// +export {} +declare const elem: HTMLElement; +>elem : HTMLElement + diff --git a/tests/baselines/reference/libReferenceDeclarationEmitBundle.js b/tests/baselines/reference/libReferenceDeclarationEmitBundle.js new file mode 100644 index 00000000000..03474372f87 --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmitBundle.js @@ -0,0 +1,30 @@ +//// [tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts] //// + +//// [file1.ts] +/// +export declare const elem: HTMLElement; + +//// [file2.ts] +/// +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] +/// +declare module "file1" { + export const elem: HTMLElement; +} +declare module "file2" { + export {}; +} diff --git a/tests/baselines/reference/libReferenceDeclarationEmitBundle.symbols b/tests/baselines/reference/libReferenceDeclarationEmitBundle.symbols new file mode 100644 index 00000000000..3753ee0b80d --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmitBundle.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +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 === +/// +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, --, --)) + diff --git a/tests/baselines/reference/libReferenceDeclarationEmitBundle.types b/tests/baselines/reference/libReferenceDeclarationEmitBundle.types new file mode 100644 index 00000000000..34102b07321 --- /dev/null +++ b/tests/baselines/reference/libReferenceDeclarationEmitBundle.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare const elem: HTMLElement; +>elem : HTMLElement + +=== tests/cases/conformance/declarationEmit/file2.ts === +/// +export {} +declare const elem: HTMLElement; +>elem : HTMLElement + diff --git a/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts b/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts new file mode 100644 index 00000000000..2afc4290776 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmit.ts @@ -0,0 +1,12 @@ +// @target: esnext +// @module: commonjs +// @lib: esnext +// @declaration: true +// @filename: file1.ts +/// +export declare const elem: HTMLElement; + +// @filename: file2.ts +/// +export {} +declare const elem: HTMLElement; \ No newline at end of file diff --git a/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts b/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts new file mode 100644 index 00000000000..e379567d559 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/libReferenceDeclarationEmitBundle.ts @@ -0,0 +1,13 @@ +// @target: esnext +// @module: amd +// @lib: esnext +// @declaration: true +// @outFile: bundle.js +// @filename: file1.ts +/// +export declare const elem: HTMLElement; + +// @filename: file2.ts +/// +export {} +declare const elem: HTMLElement; \ No newline at end of file