Merge pull request #30971 from Microsoft/dtsSignatureChange
Handle when change in type of dts may result in only dts emit but not js emit
This commit is contained in:
commit
f27cf9b34e
|
@ -238,10 +238,7 @@ namespace ts {
|
||||||
|
|
||||||
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
|
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
|
||||||
// Add all files to affectedFilesPendingEmit since emit changed
|
// Add all files to affectedFilesPendingEmit since emit changed
|
||||||
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, newProgram.getSourceFiles().map(f => f.path));
|
addToAffectedFilesPendingEmit(state, newProgram.getSourceFiles().map(f => f.path));
|
||||||
if (state.affectedFilesPendingEmitIndex === undefined) {
|
|
||||||
state.affectedFilesPendingEmitIndex = 0;
|
|
||||||
}
|
|
||||||
Debug.assert(state.seenAffectedFiles === undefined);
|
Debug.assert(state.seenAffectedFiles === undefined);
|
||||||
state.seenAffectedFiles = createMap<true>();
|
state.seenAffectedFiles = createMap<true>();
|
||||||
}
|
}
|
||||||
|
@ -339,7 +336,7 @@ namespace ts {
|
||||||
if (!seenAffectedFiles.has(affectedFile.path)) {
|
if (!seenAffectedFiles.has(affectedFile.path)) {
|
||||||
// Set the next affected file as seen and remove the cached semantic diagnostics
|
// Set the next affected file as seen and remove the cached semantic diagnostics
|
||||||
state.affectedFilesIndex = affectedFilesIndex;
|
state.affectedFilesIndex = affectedFilesIndex;
|
||||||
cleanSemanticDiagnosticsOfAffectedFile(state, affectedFile);
|
handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, computeHash);
|
||||||
return affectedFile;
|
return affectedFile;
|
||||||
}
|
}
|
||||||
seenAffectedFiles.set(affectedFile.path, true);
|
seenAffectedFiles.set(affectedFile.path, true);
|
||||||
|
@ -406,106 +403,64 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the semantic diagnostics cached from old state for affected File and the files that are referencing modules that export entities from affected file
|
* 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 cleanSemanticDiagnosticsOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile) {
|
function handleDtsMayChangeOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash) {
|
||||||
if (removeSemanticDiagnosticsOf(state, affectedFile.path)) {
|
removeSemanticDiagnosticsOf(state, affectedFile.path);
|
||||||
// If there are no more diagnostics from old cache, done
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean lib file diagnostics if its all files excluding default files to emit
|
// If affected files is everything except default library, then nothing more to do
|
||||||
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles && !state.cleanedDiagnosticsOfLibFiles) {
|
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles) {
|
||||||
|
if (!state.cleanedDiagnosticsOfLibFiles) {
|
||||||
state.cleanedDiagnosticsOfLibFiles = true;
|
state.cleanedDiagnosticsOfLibFiles = true;
|
||||||
const program = Debug.assertDefined(state.program);
|
const program = Debug.assertDefined(state.program);
|
||||||
const options = program.getCompilerOptions();
|
const options = program.getCompilerOptions();
|
||||||
if (forEach(program.getSourceFiles(), f =>
|
forEach(program.getSourceFiles(), f =>
|
||||||
program.isSourceFileDefaultLibrary(f) &&
|
program.isSourceFileDefaultLibrary(f) &&
|
||||||
!skipTypeChecking(f, options) &&
|
!skipTypeChecking(f, options) &&
|
||||||
removeSemanticDiagnosticsOf(state, f.path)
|
removeSemanticDiagnosticsOf(state, f.path)
|
||||||
)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there was change in signature for the changed file,
|
|
||||||
// then delete the semantic diagnostics for files that are affected by using exports of this module
|
|
||||||
|
|
||||||
if (!state.exportedModulesMap || state.affectedFiles!.length === 1 || !state.changedFilesSet.has(affectedFile.path)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
|
|
||||||
const seenFileAndExportsOfFile = createMap<true>();
|
|
||||||
// Go through exported modules from cache first
|
|
||||||
// If exported modules has path, all files referencing file exported from are affected
|
|
||||||
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
|
|
||||||
exportedModules &&
|
|
||||||
exportedModules.has(affectedFile.path) &&
|
|
||||||
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile)
|
|
||||||
)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
|
|
||||||
forEachEntry(state.exportedModulesMap, (exportedModules, exportedFromPath) =>
|
|
||||||
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
|
|
||||||
exportedModules.has(affectedFile.path) &&
|
|
||||||
removeSemanticDiagnosticsOfFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEachReferencingModulesOfExportOfAffectedFile(state, affectedFile, (state, path) => handleDtsMayChangeOf(state, path, cancellationToken, computeHash));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes the semantic diagnostics of files referencing referencedPath and
|
* Handle the dts may change, so they need to be added to pending emit if dts emit is enabled,
|
||||||
* returns true if there are no more semantic diagnostics from old state
|
* Also we need to make sure signature is updated for these files
|
||||||
*/
|
*/
|
||||||
function removeSemanticDiagnosticsOfFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Map<true>) {
|
function handleDtsMayChangeOf(state: BuilderProgramState, path: Path, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash) {
|
||||||
return forEachEntry(state.referencedMap!, (referencesInFile, filePath) =>
|
removeSemanticDiagnosticsOf(state, path);
|
||||||
referencesInFile.has(referencedPath) && removeSemanticDiagnosticsOfFileAndExportsOfFile(state, filePath as Path, seenFileAndExportsOfFile)
|
|
||||||
|
if (!state.changedFilesSet.has(path)) {
|
||||||
|
const program = Debug.assertDefined(state.program);
|
||||||
|
const sourceFile = program.getSourceFileByPath(path);
|
||||||
|
if (sourceFile) {
|
||||||
|
// Even though the js emit doesnt change and we are already handling dts emit and semantic diagnostics
|
||||||
|
// we need to update the signature to reflect correctness of the signature(which is output d.ts emit) of this file
|
||||||
|
// This ensures that we dont later during incremental builds considering wrong signature.
|
||||||
|
// Eg where this also is needed to ensure that .tsbuildinfo generated by incremental build should be same as if it was first fresh build
|
||||||
|
BuilderState.updateShapeSignature(
|
||||||
|
state,
|
||||||
|
program,
|
||||||
|
sourceFile,
|
||||||
|
Debug.assertDefined(state.currentAffectedFilesSignatures),
|
||||||
|
cancellationToken,
|
||||||
|
computeHash,
|
||||||
|
state.currentAffectedFilesExportedModulesMap
|
||||||
);
|
);
|
||||||
|
// If not dts emit, nothing more to do
|
||||||
|
if (getEmitDeclarations(state.compilerOptions)) {
|
||||||
|
addToAffectedFilesPendingEmit(state, [path]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes semantic diagnostics of file and anything that exports this file
|
|
||||||
*/
|
|
||||||
function removeSemanticDiagnosticsOfFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Map<true>): boolean {
|
|
||||||
if (!addToSeen(seenFileAndExportsOfFile, filePath)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeSemanticDiagnosticsOf(state, filePath)) {
|
|
||||||
// If there are no more diagnostics from old cache, done
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
|
|
||||||
// Go through exported modules from cache first
|
|
||||||
// If exported modules has path, all files referencing file exported from are affected
|
|
||||||
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
|
|
||||||
exportedModules &&
|
|
||||||
exportedModules.has(filePath) &&
|
|
||||||
removeSemanticDiagnosticsOfFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile)
|
|
||||||
)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
|
|
||||||
if (forEachEntry(state.exportedModulesMap!, (exportedModules, exportedFromPath) =>
|
|
||||||
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
|
|
||||||
exportedModules.has(filePath) &&
|
|
||||||
removeSemanticDiagnosticsOfFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile)
|
|
||||||
)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove diagnostics of files that import this file (without going to exports of referencing files)
|
|
||||||
return !!forEachEntry(state.referencedMap!, (referencesInFile, referencingFilePath) =>
|
|
||||||
referencesInFile.has(filePath) &&
|
|
||||||
!seenFileAndExportsOfFile.has(referencingFilePath) && // Not already removed diagnostic file
|
|
||||||
removeSemanticDiagnosticsOf(state, referencingFilePath as Path) // Dont add to seen since this is not yet done with the export removal
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes semantic diagnostics for path and
|
* Removes semantic diagnostics for path and
|
||||||
* returns true if there are no more semantic diagnostics from the old state
|
* returns true if there are no more semantic diagnostics from the old state
|
||||||
|
@ -519,6 +474,87 @@ namespace ts {
|
||||||
return !state.semanticDiagnosticsFromOldState.size;
|
return !state.semanticDiagnosticsFromOldState.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate on referencing modules that export entities from affected file
|
||||||
|
*/
|
||||||
|
function forEachReferencingModulesOfExportOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, fn: (state: BuilderProgramState, filePath: Path) => boolean) {
|
||||||
|
// 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.affectedFiles!.length === 1 || !state.changedFilesSet.has(affectedFile.path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
|
||||||
|
const seenFileAndExportsOfFile = createMap<true>();
|
||||||
|
// Go through exported modules from cache first
|
||||||
|
// If exported modules has path, all files referencing file exported from are affected
|
||||||
|
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
|
||||||
|
exportedModules &&
|
||||||
|
exportedModules.has(affectedFile.path) &&
|
||||||
|
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||||
|
)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
|
||||||
|
forEachEntry(state.exportedModulesMap, (exportedModules, exportedFromPath) =>
|
||||||
|
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
|
||||||
|
exportedModules.has(affectedFile.path) &&
|
||||||
|
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate on files referencing referencedPath
|
||||||
|
*/
|
||||||
|
function forEachFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Map<true>, fn: (state: BuilderProgramState, filePath: Path) => boolean) {
|
||||||
|
return forEachEntry(state.referencedMap!, (referencesInFile, filePath) =>
|
||||||
|
referencesInFile.has(referencedPath) && forEachFileAndExportsOfFile(state, filePath as Path, seenFileAndExportsOfFile, fn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fn on file and iterate on anything that exports this file
|
||||||
|
*/
|
||||||
|
function forEachFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Map<true>, fn: (state: BuilderProgramState, filePath: Path) => boolean): boolean {
|
||||||
|
if (!addToSeen(seenFileAndExportsOfFile, filePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fn(state, filePath)) {
|
||||||
|
// If there are no more diagnostics from old cache, done
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
|
||||||
|
// Go through exported modules from cache first
|
||||||
|
// If exported modules has path, all files referencing file exported from are affected
|
||||||
|
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
|
||||||
|
exportedModules &&
|
||||||
|
exportedModules.has(filePath) &&
|
||||||
|
forEachFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||||
|
)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
|
||||||
|
if (forEachEntry(state.exportedModulesMap!, (exportedModules, exportedFromPath) =>
|
||||||
|
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
|
||||||
|
exportedModules.has(filePath) &&
|
||||||
|
forEachFileAndExportsOfFile(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||||
|
)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove diagnostics of files that import this file (without going to exports of referencing files)
|
||||||
|
return !!forEachEntry(state.referencedMap!, (referencesInFile, referencingFilePath) =>
|
||||||
|
referencesInFile.has(filePath) &&
|
||||||
|
!seenFileAndExportsOfFile.has(referencingFilePath) && // Not already removed diagnostic file
|
||||||
|
fn(state, referencingFilePath as Path) // Dont add to seen since this is not yet done with the export removal
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called after completing operation on the next affected file.
|
* 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
|
* The operations here are postponed to ensure that cancellation during the iteration is handled correctly
|
||||||
|
@ -808,11 +844,6 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark seen emitted files if there are pending files to be emitted
|
|
||||||
if (state.affectedFilesPendingEmit && state.program !== affected) {
|
|
||||||
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toAffectedFileResult(
|
return toAffectedFileResult(
|
||||||
state,
|
state,
|
||||||
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
|
||||||
|
@ -931,14 +962,7 @@ namespace ts {
|
||||||
|
|
||||||
// In case of emit builder, cache the files to be emitted
|
// In case of emit builder, cache the files to be emitted
|
||||||
if (affectedFilesPendingEmit) {
|
if (affectedFilesPendingEmit) {
|
||||||
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, affectedFilesPendingEmit);
|
addToAffectedFilesPendingEmit(state, affectedFilesPendingEmit);
|
||||||
// affectedFilesPendingEmitIndex === undefined
|
|
||||||
// - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
|
|
||||||
// so start from 0 as array would be affectedFilesPendingEmit
|
|
||||||
// else, continue to iterate from existing index, the current set is appended to existing files
|
|
||||||
if (state.affectedFilesPendingEmitIndex === undefined) {
|
|
||||||
state.affectedFilesPendingEmitIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let diagnostics: Diagnostic[] | undefined;
|
let diagnostics: Diagnostic[] | undefined;
|
||||||
|
@ -949,6 +973,17 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilesPendingEmit: readonly Path[]) {
|
||||||
|
state.affectedFilesPendingEmit = concatenate(state.affectedFilesPendingEmit, affectedFilesPendingEmit);
|
||||||
|
// affectedFilesPendingEmitIndex === undefined
|
||||||
|
// - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
|
||||||
|
// so start from 0 as array would be affectedFilesPendingEmit
|
||||||
|
// else, continue to iterate from existing index, the current set is appended to existing files
|
||||||
|
if (state.affectedFilesPendingEmitIndex === undefined) {
|
||||||
|
state.affectedFilesPendingEmitIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getMapOfReferencedSet(mapLike: MapLike<ReadonlyArray<string>> | undefined): ReadonlyMap<BuilderState.ReferencedSet> | undefined {
|
function getMapOfReferencedSet(mapLike: MapLike<ReadonlyArray<string>> | undefined): ReadonlyMap<BuilderState.ReferencedSet> | undefined {
|
||||||
if (!mapLike) return undefined;
|
if (!mapLike) return undefined;
|
||||||
const map = createMap<BuilderState.ReferencedSet>();
|
const map = createMap<BuilderState.ReferencedSet>();
|
||||||
|
|
|
@ -321,7 +321,7 @@ namespace ts.BuilderState {
|
||||||
/**
|
/**
|
||||||
* Returns if the shape of the signature has changed since last emit
|
* Returns if the shape of the signature has changed since last emit
|
||||||
*/
|
*/
|
||||||
function updateShapeSignature(state: Readonly<BuilderState>, programOfThisState: Program, sourceFile: SourceFile, cacheToUpdateSignature: Map<string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache?: ComputingExportedModulesMap) {
|
export function updateShapeSignature(state: Readonly<BuilderState>, programOfThisState: Program, sourceFile: SourceFile, cacheToUpdateSignature: Map<string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache?: ComputingExportedModulesMap) {
|
||||||
Debug.assert(!!sourceFile);
|
Debug.assert(!!sourceFile);
|
||||||
Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state");
|
Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state");
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
"unittests/tsbuild/amdModulesWithOut.ts",
|
"unittests/tsbuild/amdModulesWithOut.ts",
|
||||||
"unittests/tsbuild/emptyFiles.ts",
|
"unittests/tsbuild/emptyFiles.ts",
|
||||||
"unittests/tsbuild/graphOrdering.ts",
|
"unittests/tsbuild/graphOrdering.ts",
|
||||||
|
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
|
||||||
"unittests/tsbuild/lateBoundSymbol.ts",
|
"unittests/tsbuild/lateBoundSymbol.ts",
|
||||||
"unittests/tsbuild/missingExtendedFile.ts",
|
"unittests/tsbuild/missingExtendedFile.ts",
|
||||||
"unittests/tsbuild/outFile.ts",
|
"unittests/tsbuild/outFile.ts",
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
namespace ts {
|
||||||
|
describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||||
|
let projFs: vfs.FileSystem;
|
||||||
|
const { time, tick } = getTime();
|
||||||
|
before(() => {
|
||||||
|
projFs = loadProjectFromDisk("tests/projects/inferredTypeFromTransitiveModule", time);
|
||||||
|
});
|
||||||
|
after(() => {
|
||||||
|
projFs = undefined!;
|
||||||
|
});
|
||||||
|
|
||||||
|
verifyTsbuildOutput({
|
||||||
|
scenario: "inferred type from transitive module",
|
||||||
|
projFs: () => projFs,
|
||||||
|
time,
|
||||||
|
tick,
|
||||||
|
proj: "inferredTypeFromTransitiveModule",
|
||||||
|
rootNames: ["/src"],
|
||||||
|
expectedMapFileNames: emptyArray,
|
||||||
|
lastProjectOutputJs: `/src/obj/index.js`,
|
||||||
|
outputFiles: [
|
||||||
|
"/src/obj/bar.js", "/src/obj/bar.d.ts",
|
||||||
|
"/src/obj/bundling.js", "/src/obj/bundling.d.ts",
|
||||||
|
"/src/obj/lazyIndex.js", "/src/obj/lazyIndex.d.ts",
|
||||||
|
"/src/obj/index.js", "/src/obj/index.d.ts",
|
||||||
|
"/src/obj/tsconfig.tsbuildinfo"
|
||||||
|
],
|
||||||
|
initialBuild: {
|
||||||
|
modifyFs: noop,
|
||||||
|
expectedDiagnostics: [
|
||||||
|
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||||
|
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tsconfig.json", "src/obj/bar.js"],
|
||||||
|
[Diagnostics.Building_project_0, "/src/tsconfig.json"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
incrementalDtsChangedBuild: {
|
||||||
|
modifyFs: fs => replaceText(fs, "/src/bar.ts", "param: string", ""),
|
||||||
|
expectedDiagnostics: [
|
||||||
|
getExpectedDiagnosticForProjectsInBuild("src/tsconfig.json"),
|
||||||
|
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, "src/tsconfig.json", "src/obj/bar.js", "src/bar.ts"],
|
||||||
|
[Diagnostics.Building_project_0, "/src/tsconfig.json"],
|
||||||
|
[Diagnostics.Updating_unchanged_output_timestamps_of_project_0, "/src/tsconfig.json"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
baselineOnly: true,
|
||||||
|
verifyDiagnostics: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
//// [/src/bar.ts]
|
||||||
|
interface RawAction {
|
||||||
|
(...args: any[]): Promise<any> | void;
|
||||||
|
}
|
||||||
|
interface ActionFactory {
|
||||||
|
<T extends RawAction>(target: T): T;
|
||||||
|
}
|
||||||
|
declare function foo<U extends any[] = any[]>(): ActionFactory;
|
||||||
|
export default foo()(function foobar(): void {
|
||||||
|
});
|
||||||
|
|
||||||
|
//// [/src/obj/bar.d.ts]
|
||||||
|
declare const _default: () => void;
|
||||||
|
export default _default;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/bar.js]
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.default = foo()(function foobar() {
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/index.d.ts]
|
||||||
|
import { LazyAction } from './bundling';
|
||||||
|
export declare const lazyBar: LazyAction<() => void, typeof import("./lazyIndex")>;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/tsconfig.tsbuildinfo]
|
||||||
|
{
|
||||||
|
"program": {
|
||||||
|
"fileInfos": {
|
||||||
|
"/lib/lib.d.ts": {
|
||||||
|
"version": "-15964756381",
|
||||||
|
"signature": "-15964756381"
|
||||||
|
},
|
||||||
|
"/src/bar.ts": {
|
||||||
|
"version": "747071916",
|
||||||
|
"signature": "-9232740537"
|
||||||
|
},
|
||||||
|
"/src/bundling.ts": {
|
||||||
|
"version": "-21659820217",
|
||||||
|
"signature": "-40032907372"
|
||||||
|
},
|
||||||
|
"/src/global.d.ts": {
|
||||||
|
"version": "-9780226215",
|
||||||
|
"signature": "-9780226215"
|
||||||
|
},
|
||||||
|
"/src/lazyindex.ts": {
|
||||||
|
"version": "-6956449754",
|
||||||
|
"signature": "-6224542381"
|
||||||
|
},
|
||||||
|
"/src/index.ts": {
|
||||||
|
"version": "-11602502901",
|
||||||
|
"signature": "6256067474"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"target": 1,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "/src/obj",
|
||||||
|
"incremental": true,
|
||||||
|
"configFilePath": "/src/tsconfig.json"
|
||||||
|
},
|
||||||
|
"referencedMap": {
|
||||||
|
"/src/index.ts": [
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
],
|
||||||
|
"/src/lazyindex.ts": [
|
||||||
|
"/src/bar.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exportedModulesMap": {
|
||||||
|
"/src/index.ts": [
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
],
|
||||||
|
"/src/lazyindex.ts": [
|
||||||
|
"/src/bar.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"semanticDiagnosticsPerFile": [
|
||||||
|
"/lib/lib.d.ts",
|
||||||
|
"/src/bar.ts",
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/global.d.ts",
|
||||||
|
"/src/index.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"version": "FakeTSVersion"
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
//// [/src/obj/bar.d.ts]
|
||||||
|
declare const _default: (param: string) => void;
|
||||||
|
export default _default;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/bar.js]
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.default = foo()(function foobar(param) {
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/bundling.d.ts]
|
||||||
|
export declare class LazyModule<TModule> {
|
||||||
|
private importCallback;
|
||||||
|
constructor(importCallback: () => Promise<TModule>);
|
||||||
|
}
|
||||||
|
export declare class LazyAction<TAction extends (...args: any[]) => any, TModule> {
|
||||||
|
constructor(_lazyModule: LazyModule<TModule>, _getter: (module: TModule) => TAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/bundling.js]
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var LazyModule = /** @class */ (function () {
|
||||||
|
function LazyModule(importCallback) {
|
||||||
|
this.importCallback = importCallback;
|
||||||
|
}
|
||||||
|
return LazyModule;
|
||||||
|
}());
|
||||||
|
exports.LazyModule = LazyModule;
|
||||||
|
var LazyAction = /** @class */ (function () {
|
||||||
|
function LazyAction(_lazyModule, _getter) {
|
||||||
|
}
|
||||||
|
return LazyAction;
|
||||||
|
}());
|
||||||
|
exports.LazyAction = LazyAction;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/index.d.ts]
|
||||||
|
import { LazyAction } from './bundling';
|
||||||
|
export declare const lazyBar: LazyAction<(param: string) => void, typeof import("./lazyIndex")>;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/index.js]
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var bundling_1 = require("./bundling");
|
||||||
|
var lazyModule = new bundling_1.LazyModule(function () {
|
||||||
|
return Promise.resolve().then(function () { return require('./lazyIndex'); });
|
||||||
|
});
|
||||||
|
exports.lazyBar = new bundling_1.LazyAction(lazyModule, function (m) { return m.bar; });
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/lazyIndex.d.ts]
|
||||||
|
export { default as bar } from './bar';
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/lazyIndex.js]
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var bar_1 = require("./bar");
|
||||||
|
exports.bar = bar_1.default;
|
||||||
|
|
||||||
|
|
||||||
|
//// [/src/obj/tsconfig.tsbuildinfo]
|
||||||
|
{
|
||||||
|
"program": {
|
||||||
|
"fileInfos": {
|
||||||
|
"/lib/lib.d.ts": {
|
||||||
|
"version": "-15964756381",
|
||||||
|
"signature": "-15964756381"
|
||||||
|
},
|
||||||
|
"/src/bar.ts": {
|
||||||
|
"version": "5936740878",
|
||||||
|
"signature": "11191036521"
|
||||||
|
},
|
||||||
|
"/src/bundling.ts": {
|
||||||
|
"version": "-21659820217",
|
||||||
|
"signature": "-40032907372"
|
||||||
|
},
|
||||||
|
"/src/global.d.ts": {
|
||||||
|
"version": "-9780226215",
|
||||||
|
"signature": "-9780226215"
|
||||||
|
},
|
||||||
|
"/src/lazyindex.ts": {
|
||||||
|
"version": "-6956449754",
|
||||||
|
"signature": "-6224542381"
|
||||||
|
},
|
||||||
|
"/src/index.ts": {
|
||||||
|
"version": "-11602502901",
|
||||||
|
"signature": "18468008756"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"target": 1,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "/src/obj",
|
||||||
|
"incremental": true,
|
||||||
|
"configFilePath": "/src/tsconfig.json"
|
||||||
|
},
|
||||||
|
"referencedMap": {
|
||||||
|
"/src/index.ts": [
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
],
|
||||||
|
"/src/lazyindex.ts": [
|
||||||
|
"/src/bar.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exportedModulesMap": {
|
||||||
|
"/src/index.ts": [
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
],
|
||||||
|
"/src/lazyindex.ts": [
|
||||||
|
"/src/bar.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"semanticDiagnosticsPerFile": [
|
||||||
|
"/lib/lib.d.ts",
|
||||||
|
"/src/bar.ts",
|
||||||
|
"/src/bundling.ts",
|
||||||
|
"/src/global.d.ts",
|
||||||
|
"/src/index.ts",
|
||||||
|
"/src/lazyindex.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"version": "FakeTSVersion"
|
||||||
|
}
|
||||||
|
|
9
tests/projects/inferredTypeFromTransitiveModule/bar.ts
Normal file
9
tests/projects/inferredTypeFromTransitiveModule/bar.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
interface RawAction {
|
||||||
|
(...args: any[]): Promise<any> | void;
|
||||||
|
}
|
||||||
|
interface ActionFactory {
|
||||||
|
<T extends RawAction>(target: T): T;
|
||||||
|
}
|
||||||
|
declare function foo<U extends any[] = any[]>(): ActionFactory;
|
||||||
|
export default foo()(function foobar(param: string): void {
|
||||||
|
});
|
11
tests/projects/inferredTypeFromTransitiveModule/bundling.ts
Normal file
11
tests/projects/inferredTypeFromTransitiveModule/bundling.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
export class LazyModule<TModule> {
|
||||||
|
constructor(private importCallback: () => Promise<TModule>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LazyAction<
|
||||||
|
TAction extends (...args: any[]) => any,
|
||||||
|
TModule
|
||||||
|
> {
|
||||||
|
constructor(_lazyModule: LazyModule<TModule>, _getter: (module: TModule) => TAction) {
|
||||||
|
}
|
||||||
|
}
|
6
tests/projects/inferredTypeFromTransitiveModule/global.d.ts
vendored
Normal file
6
tests/projects/inferredTypeFromTransitiveModule/global.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
interface PromiseConstructor {
|
||||||
|
new <T>(): Promise<T>;
|
||||||
|
}
|
||||||
|
declare var Promise: PromiseConstructor;
|
||||||
|
interface Promise<T> {
|
||||||
|
}
|
5
tests/projects/inferredTypeFromTransitiveModule/index.ts
Normal file
5
tests/projects/inferredTypeFromTransitiveModule/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { LazyAction, LazyModule } from './bundling';
|
||||||
|
const lazyModule = new LazyModule(() =>
|
||||||
|
import('./lazyIndex')
|
||||||
|
);
|
||||||
|
export const lazyBar = new LazyAction(lazyModule, m => m.bar);
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as bar } from './bar';
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "obj",
|
||||||
|
"incremental": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue