diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 534276354f0d1..d3a6c5d734ffe 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -433,25 +433,35 @@ namespace ts { return undefined; } + function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) { + if (!state.cleanedDiagnosticsOfLibFiles) { + state.cleanedDiagnosticsOfLibFiles = true; + const program = Debug.checkDefined(state.program); + const options = program.getCompilerOptions(); + forEach(program.getSourceFiles(), f => + program.isSourceFileDefaultLibrary(f) && + !skipTypeChecking(f, options, program) && + removeSemanticDiagnosticsOf(state, f.resolvedPath) + ); + } + } + /** * Handles semantic diagnostics and dts emit for affectedFile and files, that are referencing modules that export entities from affected file * This is because even though js emit doesnt change, dts emit / type used can change resulting in need for dts emit and js change */ - function handleDtsMayChangeOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, host: BuilderProgramHost) { + function handleDtsMayChangeOfAffectedFile( + state: BuilderProgramState, + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost, + ) { removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath); // If affected files is everything except default library, then nothing more to do if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles) { - if (!state.cleanedDiagnosticsOfLibFiles) { - state.cleanedDiagnosticsOfLibFiles = true; - const program = Debug.checkDefined(state.program); - const options = program.getCompilerOptions(); - forEach(program.getSourceFiles(), f => - program.isSourceFileDefaultLibrary(f) && - !skipTypeChecking(f, options, program) && - removeSemanticDiagnosticsOf(state, f.resolvedPath) - ); - } + removeDiagnosticsOfLibraryFiles(state); // When a change affects the global scope, all files are considered to be affected without updating their signature // That means when affected file is handled, its signature can be out of date // To avoid this, ensure that we update the signature for any affected file in this scenario. @@ -466,20 +476,22 @@ namespace ts { ); return; } - else { - Debug.assert(state.hasCalledUpdateShapeSignature.has(affectedFile.resolvedPath) || state.currentAffectedFilesSignatures?.has(affectedFile.resolvedPath), `Signature not updated for affected file: ${affectedFile.fileName}`); - } - - if (!state.compilerOptions.assumeChangesOnlyAffectDirectDependencies) { - forEachReferencingModulesOfExportOfAffectedFile(state, affectedFile, (state, path) => handleDtsMayChangeOf(state, path, cancellationToken, computeHash, host)); - } + Debug.assert(state.hasCalledUpdateShapeSignature.has(affectedFile.resolvedPath) || state.currentAffectedFilesSignatures?.has(affectedFile.resolvedPath), `Signature not updated for affected file: ${affectedFile.fileName}`); + if (state.compilerOptions.assumeChangesOnlyAffectDirectDependencies) return; + handleDtsMayChangeOfReferencingExportOfAffectedFile(state, affectedFile, cancellationToken, computeHash, host); } /** * Handle the dts may change, so they need to be added to pending emit if dts emit is enabled, * Also we need to make sure signature is updated for these files */ - function handleDtsMayChangeOf(state: BuilderProgramState, path: Path, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, host: BuilderProgramHost): void { + function handleDtsMayChangeOf( + state: BuilderProgramState, + path: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost + ): void { removeSemanticDiagnosticsOf(state, path); if (!state.changedFilesSet.has(path)) { @@ -528,16 +540,61 @@ namespace ts { return newSignature !== oldSignature; } + function forEachKeyOfExportedModulesMap( + state: BuilderProgramState, + filePath: Path, + fn: (exportedFromPath: Path) => T | undefined, + ): T | undefined { + // Go through exported modules from cache first + let keys = state.currentAffectedFilesExportedModulesMap!.getKeys(filePath); + const result = keys && forEachKey(keys, fn); + if (result) return result; + + // If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected + keys = state.exportedModulesMap!.getKeys(filePath); + return keys && forEachKey(keys, exportedFromPath => + // If the cache had an updated value, skip + !state.currentAffectedFilesExportedModulesMap!.hasKey(exportedFromPath) && + !state.currentAffectedFilesExportedModulesMap!.deletedKeys()?.has(exportedFromPath) ? + fn(exportedFromPath) : + undefined + ); + } + + function handleDtsMayChangeOfGlobalScope( + state: BuilderProgramState, + filePath: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost, + ): boolean { + if (!state.fileInfos.get(filePath)?.affectsGlobalScope) return false; + // Every file needs to be handled + BuilderState.getAllFilesExcludingDefaultLibraryFile(state, state.program!, /*firstSourceFile*/ undefined) + .forEach(file => handleDtsMayChangeOf( + state, + file.resolvedPath, + cancellationToken, + computeHash, + host, + )); + removeDiagnosticsOfLibraryFiles(state); + return true; + } + /** - * Iterate on referencing modules that export entities from affected file + * Iterate on referencing modules that export entities from affected file and delete diagnostics and add pending emit */ - function forEachReferencingModulesOfExportOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, fn: (state: BuilderProgramState, filePath: Path) => void) { + function handleDtsMayChangeOfReferencingExportOfAffectedFile( + state: BuilderProgramState, + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost + ) { // If there was change in signature (dts output) for the changed file, // then only we need to handle pending file emit - if (!state.exportedModulesMap || !state.changedFilesSet.has(affectedFile.resolvedPath)) { - return; - } - + if (!state.exportedModulesMap || !state.changedFilesSet.has(affectedFile.resolvedPath)) return; if (!isChangedSignature(state, affectedFile.resolvedPath)) return; // Since isolated modules dont change js files, files affected by change in signature is itself @@ -550,7 +607,8 @@ namespace ts { const currentPath = queue.pop()!; if (!seenFileNamesMap.has(currentPath)) { seenFileNamesMap.set(currentPath, true); - fn(state, currentPath); + if (handleDtsMayChangeOfGlobalScope(state, currentPath, cancellationToken, computeHash, host)) return; + handleDtsMayChangeOf(state, currentPath, cancellationToken, computeHash, host); if (isChangedSignature(state, currentPath)) { const currentSourceFile = Debug.checkDefined(state.program).getSourceFileByPath(currentPath)!; queue.push(...BuilderState.getReferencedByPaths(state, currentSourceFile.resolvedPath)); @@ -560,65 +618,69 @@ namespace ts { } Debug.assert(!!state.currentAffectedFilesExportedModulesMap); - const seenFileAndExportsOfFile = new Set(); // Go through exported modules from cache first // If exported modules has path, all files referencing file exported from are affected - state.currentAffectedFilesExportedModulesMap.getKeys(affectedFile.resolvedPath)?.forEach(exportedFromPath => - forEachFilesReferencingPath(state, exportedFromPath, seenFileAndExportsOfFile, fn) - ); - - // If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected - state.exportedModulesMap.getKeys(affectedFile.resolvedPath)?.forEach(exportedFromPath => - // If the cache had an updated value, skip - !state.currentAffectedFilesExportedModulesMap!.hasKey(exportedFromPath) && - !state.currentAffectedFilesExportedModulesMap!.deletedKeys()?.has(exportedFromPath) && - forEachFilesReferencingPath(state, exportedFromPath, seenFileAndExportsOfFile, fn) - ); - } - - /** - * Iterate on files referencing referencedPath - */ - function forEachFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Set, fn: (state: BuilderProgramState, filePath: Path) => void): void { - state.referencedMap!.getKeys(referencedPath)?.forEach(filePath => - forEachFileAndExportsOfFile(state, filePath, seenFileAndExportsOfFile, fn) - ); + forEachKeyOfExportedModulesMap(state, affectedFile.resolvedPath, exportedFromPath => { + if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, cancellationToken, computeHash, host)) return true; + const references = state.referencedMap!.getKeys(exportedFromPath); + return references && forEachKey(references, filePath => + handleDtsMayChangeOfFileAndExportsOfFile( + state, + filePath, + seenFileAndExportsOfFile, + cancellationToken, + computeHash, + host, + ) + ); + }); } /** - * fn on file and iterate on anything that exports this file + * handle dts and semantic diagnostics on file and iterate on anything that exports this file + * return true when all work is done and we can exit handling dts emit and semantic diagnostics */ - function forEachFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Set, fn: (state: BuilderProgramState, filePath: Path) => void): void { - if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) { - return; - } - - fn(state, filePath); - + function handleDtsMayChangeOfFileAndExportsOfFile( + state: BuilderProgramState, + filePath: Path, + seenFileAndExportsOfFile: Set, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost, + ): boolean | undefined { + if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; + + if (handleDtsMayChangeOfGlobalScope(state, filePath, cancellationToken, computeHash, host)) return true; + handleDtsMayChangeOf(state, filePath, cancellationToken, computeHash, host); Debug.assert(!!state.currentAffectedFilesExportedModulesMap); - // Go through exported modules from cache first - // If exported modules has path, all files referencing file exported from are affected - state.currentAffectedFilesExportedModulesMap.getKeys(filePath)?.forEach(exportedFromPath => - forEachFileAndExportsOfFile(state, exportedFromPath, seenFileAndExportsOfFile, fn) - ); - // If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected - state.exportedModulesMap!.getKeys(filePath)?.forEach(exportedFromPath => - // If the cache had an updated value, skip - !state.currentAffectedFilesExportedModulesMap!.hasKey(exportedFromPath) && - !state.currentAffectedFilesExportedModulesMap!.deletedKeys()?.has(exportedFromPath) && - forEachFileAndExportsOfFile(state, exportedFromPath, seenFileAndExportsOfFile, fn) + // If exported modules has path, all files referencing file exported from are affected + forEachKeyOfExportedModulesMap(state, filePath, exportedFromPath => + handleDtsMayChangeOfFileAndExportsOfFile( + state, + exportedFromPath, + seenFileAndExportsOfFile, + cancellationToken, + computeHash, + host, + ) ); // Remove diagnostics of files that import this file (without going to exports of referencing files) state.referencedMap!.getKeys(filePath)?.forEach(referencingFilePath => !seenFileAndExportsOfFile.has(referencingFilePath) && // Not already removed diagnostic file - fn(state, referencingFilePath) // Dont add to seen since this is not yet done with the export removal + handleDtsMayChangeOf( // Dont add to seen since this is not yet done with the export removal + state, + referencingFilePath, + cancellationToken, + computeHash, + host, + ) ); + return undefined; } - /** * This is called after completing operation on the next affected file. * The operations here are postponed to ensure that cancellation during the iteration is handled correctly diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index ec5093e0849a9..a27b1b9025380 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -464,5 +464,40 @@ declare global { fs.writeFileSync("/lib/lib.esnext.d.ts", libContent); } }); + + verifyTscWithEdits({ + scenario: "incremental", + subScenario: "change to type that gets used as global through export in another file", + commandLineArgs: ["-p", `src/project`], + fs: () => loadProjectFromFiles({ + "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { composite: true }, }), + "/src/project/class1.ts": `const a: MagicNumber = 1; +console.log(a);`, + "/src/project/constants.ts": "export default 1;", + "/src/project/types.d.ts": `type MagicNumber = typeof import('./constants').default`, + }), + edits: [{ + subScenario: "Modify imports used in global file", + modifyFs: fs => fs.writeFileSync("/src/project/constants.ts", "export default 2;"), + }], + }); + + verifyTscWithEdits({ + scenario: "incremental", + subScenario: "change to type that gets used as global through export in another file through indirect import", + commandLineArgs: ["-p", `src/project`], + fs: () => loadProjectFromFiles({ + "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { composite: true }, }), + "/src/project/class1.ts": `const a: MagicNumber = 1; +console.log(a);`, + "/src/project/constants.ts": "export default 1;", + "/src/project/reexport.ts": `export { default as ConstantNumber } from "./constants"`, + "/src/project/types.d.ts": `type MagicNumber = typeof import('./reexport').ConstantNumber`, + }), + edits: [{ + subScenario: "Modify imports used in global file", + modifyFs: fs => fs.writeFileSync("/src/project/constants.ts", "export default 2;"), + }], + }); }); } diff --git a/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file-through-indirect-import.js b/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file-through-indirect-import.js new file mode 100644 index 0000000000000..13414c757da26 --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file-through-indirect-import.js @@ -0,0 +1,287 @@ +Input:: +//// [/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + +//// [/src/project/class1.ts] +const a: MagicNumber = 1; +console.log(a); + +//// [/src/project/constants.ts] +export default 1; + +//// [/src/project/reexport.ts] +export { default as ConstantNumber } from "./constants" + +//// [/src/project/tsconfig.json] +{"compilerOptions":{"composite":true}} + +//// [/src/project/types.d.ts] +type MagicNumber = typeof import('./reexport').ConstantNumber + + + +Output:: +/lib/tsc -p src/project +exitCode:: ExitStatus.Success + + +//// [/src/project/class1.d.ts] +declare const a = 1; + + +//// [/src/project/class1.js] +var a = 1; +console.log(a); + + +//// [/src/project/constants.d.ts] +declare const _default: 1; +export default _default; + + +//// [/src/project/constants.js] +"use strict"; +exports.__esModule = true; +exports["default"] = 1; + + +//// [/src/project/reexport.d.ts] +export { default as ConstantNumber } from "./constants"; + + +//// [/src/project/reexport.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +exports.__esModule = true; +exports.ConstantNumber = void 0; +var constants_1 = require("./constants"); +__createBinding(exports, constants_1, "default", "ConstantNumber"); + + +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./class1.ts","./constants.ts","./reexport.ts","./types.d.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"4085502068-const a: MagicNumber = 1;\nconsole.log(a);","affectsGlobalScope":true},"-2659799048-export default 1;","-1476032387-export { default as ConstantNumber } from \"./constants\"",{"version":"2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber","affectsGlobalScope":true}],"options":{"composite":true},"fileIdsList":[[3],[4]],"referencedMap":[[4,1],[5,2]],"exportedModulesMap":[[4,1],[5,2]],"semanticDiagnosticsPerFile":[1,2,3,4,5]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./reexport.ts", + "./types.d.ts" + ], + "fileNamesList": [ + [ + "./constants.ts" + ], + [ + "./reexport.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "./class1.ts": { + "version": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "signature": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "affectsGlobalScope": true + }, + "./constants.ts": { + "version": "-2659799048-export default 1;", + "signature": "-2659799048-export default 1;" + }, + "./reexport.ts": { + "version": "-1476032387-export { default as ConstantNumber } from \"./constants\"", + "signature": "-1476032387-export { default as ConstantNumber } from \"./constants\"" + }, + "./types.d.ts": { + "version": "2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber", + "signature": "2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber", + "affectsGlobalScope": true + } + }, + "options": { + "composite": true + }, + "referencedMap": { + "./reexport.ts": [ + "./constants.ts" + ], + "./types.d.ts": [ + "./reexport.ts" + ] + }, + "exportedModulesMap": { + "./reexport.ts": [ + "./constants.ts" + ], + "./types.d.ts": [ + "./reexport.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./reexport.ts", + "./types.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1099 +} + + + +Change:: Modify imports used in global file +Input:: +//// [/src/project/constants.ts] +export default 2; + + + +Output:: +/lib/tsc -p src/project +src/project/class1.ts:1:7 - error TS2322: Type '1' is not assignable to type '2'. + +1 const a: MagicNumber = 1; +   ~ + + +Found 1 error in src/project/class1.ts:1 + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + +//// [/src/project/class1.d.ts] +declare const a = 2; + + +//// [/src/project/constants.d.ts] +declare const _default: 2; +export default _default; + + +//// [/src/project/constants.js] +"use strict"; +exports.__esModule = true; +exports["default"] = 2; + + +//// [/src/project/reexport.d.ts] file written with same contents +//// [/src/project/reexport.js] file written with same contents +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./class1.ts","./constants.ts","./reexport.ts","./types.d.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"4085502068-const a: MagicNumber = 1;\nconsole.log(a);","affectsGlobalScope":true},{"version":"-2659799015-export default 2;","signature":"1573564507-declare const _default: 2;\r\nexport default _default;\r\n"},{"version":"-1476032387-export { default as ConstantNumber } from \"./constants\"","signature":"-1329721329-export { default as ConstantNumber } from \"./constants\";\r\n"},{"version":"2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber","affectsGlobalScope":true}],"options":{"composite":true},"fileIdsList":[[3],[4]],"referencedMap":[[4,1],[5,2]],"exportedModulesMap":[[4,1],[5,2]],"semanticDiagnosticsPerFile":[1,[2,[{"file":"./class1.ts","start":6,"length":1,"code":2322,"category":1,"messageText":"Type '1' is not assignable to type '2'."}]],3,4,5]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./reexport.ts", + "./types.d.ts" + ], + "fileNamesList": [ + [ + "./constants.ts" + ], + [ + "./reexport.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "./class1.ts": { + "version": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "signature": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "affectsGlobalScope": true + }, + "./constants.ts": { + "version": "-2659799015-export default 2;", + "signature": "1573564507-declare const _default: 2;\r\nexport default _default;\r\n" + }, + "./reexport.ts": { + "version": "-1476032387-export { default as ConstantNumber } from \"./constants\"", + "signature": "-1329721329-export { default as ConstantNumber } from \"./constants\";\r\n" + }, + "./types.d.ts": { + "version": "2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber", + "signature": "2093085814-type MagicNumber = typeof import('./reexport').ConstantNumber", + "affectsGlobalScope": true + } + }, + "options": { + "composite": true + }, + "referencedMap": { + "./reexport.ts": [ + "./constants.ts" + ], + "./types.d.ts": [ + "./reexport.ts" + ] + }, + "exportedModulesMap": { + "./reexport.ts": [ + "./constants.ts" + ], + "./types.d.ts": [ + "./reexport.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + [ + "./class1.ts", + [ + { + "file": "./class1.ts", + "start": 6, + "length": 1, + "code": 2322, + "category": 1, + "messageText": "Type '1' is not assignable to type '2'." + } + ] + ], + "./constants.ts", + "./reexport.ts", + "./types.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1425 +} + diff --git a/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file.js b/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file.js new file mode 100644 index 0000000000000..a64e6e273ade9 --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/change-to-type-that-gets-used-as-global-through-export-in-another-file.js @@ -0,0 +1,229 @@ +Input:: +//// [/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + +//// [/src/project/class1.ts] +const a: MagicNumber = 1; +console.log(a); + +//// [/src/project/constants.ts] +export default 1; + +//// [/src/project/tsconfig.json] +{"compilerOptions":{"composite":true}} + +//// [/src/project/types.d.ts] +type MagicNumber = typeof import('./constants').default + + + +Output:: +/lib/tsc -p src/project +exitCode:: ExitStatus.Success + + +//// [/src/project/class1.d.ts] +declare const a = 1; + + +//// [/src/project/class1.js] +var a = 1; +console.log(a); + + +//// [/src/project/constants.d.ts] +declare const _default: 1; +export default _default; + + +//// [/src/project/constants.js] +"use strict"; +exports.__esModule = true; +exports["default"] = 1; + + +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./class1.ts","./constants.ts","./types.d.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"4085502068-const a: MagicNumber = 1;\nconsole.log(a);","affectsGlobalScope":true},"-2659799048-export default 1;",{"version":"-2080821236-type MagicNumber = typeof import('./constants').default","affectsGlobalScope":true}],"options":{"composite":true},"fileIdsList":[[3]],"referencedMap":[[4,1]],"exportedModulesMap":[[4,1]],"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./types.d.ts" + ], + "fileNamesList": [ + [ + "./constants.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "./class1.ts": { + "version": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "signature": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "affectsGlobalScope": true + }, + "./constants.ts": { + "version": "-2659799048-export default 1;", + "signature": "-2659799048-export default 1;" + }, + "./types.d.ts": { + "version": "-2080821236-type MagicNumber = typeof import('./constants').default", + "signature": "-2080821236-type MagicNumber = typeof import('./constants').default", + "affectsGlobalScope": true + } + }, + "options": { + "composite": true + }, + "referencedMap": { + "./types.d.ts": [ + "./constants.ts" + ] + }, + "exportedModulesMap": { + "./types.d.ts": [ + "./constants.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./types.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 988 +} + + + +Change:: Modify imports used in global file +Input:: +//// [/src/project/constants.ts] +export default 2; + + + +Output:: +/lib/tsc -p src/project +src/project/class1.ts:1:7 - error TS2322: Type '1' is not assignable to type '2'. + +1 const a: MagicNumber = 1; +   ~ + + +Found 1 error in src/project/class1.ts:1 + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + +//// [/src/project/class1.d.ts] +declare const a = 2; + + +//// [/src/project/constants.d.ts] +declare const _default: 2; +export default _default; + + +//// [/src/project/constants.js] +"use strict"; +exports.__esModule = true; +exports["default"] = 2; + + +//// [/src/project/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../lib/lib.d.ts","./class1.ts","./constants.ts","./types.d.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"4085502068-const a: MagicNumber = 1;\nconsole.log(a);","affectsGlobalScope":true},{"version":"-2659799015-export default 2;","signature":"1573564507-declare const _default: 2;\r\nexport default _default;\r\n"},{"version":"-2080821236-type MagicNumber = typeof import('./constants').default","affectsGlobalScope":true}],"options":{"composite":true},"fileIdsList":[[3]],"referencedMap":[[4,1]],"exportedModulesMap":[[4,1]],"semanticDiagnosticsPerFile":[1,[2,[{"file":"./class1.ts","start":6,"length":1,"code":2322,"category":1,"messageText":"Type '1' is not assignable to type '2'."}]],3,4]},"version":"FakeTSVersion"} + +//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../lib/lib.d.ts", + "./class1.ts", + "./constants.ts", + "./types.d.ts" + ], + "fileNamesList": [ + [ + "./constants.ts" + ] + ], + "fileInfos": { + "../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "./class1.ts": { + "version": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "signature": "4085502068-const a: MagicNumber = 1;\nconsole.log(a);", + "affectsGlobalScope": true + }, + "./constants.ts": { + "version": "-2659799015-export default 2;", + "signature": "1573564507-declare const _default: 2;\r\nexport default _default;\r\n" + }, + "./types.d.ts": { + "version": "-2080821236-type MagicNumber = typeof import('./constants').default", + "signature": "-2080821236-type MagicNumber = typeof import('./constants').default", + "affectsGlobalScope": true + } + }, + "options": { + "composite": true + }, + "referencedMap": { + "./types.d.ts": [ + "./constants.ts" + ] + }, + "exportedModulesMap": { + "./types.d.ts": [ + "./constants.ts" + ] + }, + "semanticDiagnosticsPerFile": [ + "../../lib/lib.d.ts", + [ + "./class1.ts", + [ + { + "file": "./class1.ts", + "start": 6, + "length": 1, + "code": 2322, + "category": 1, + "messageText": "Type '1' is not assignable to type '2'." + } + ] + ], + "./constants.ts", + "./types.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1213 +} +