mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Use resolvedPath consistently in the builder (#35757)
* Add baseline for #35468 * Use resolvedPath consistently in the builder Fixes #35468
This commit is contained in:
@@ -246,7 +246,7 @@ namespace ts {
|
||||
|
||||
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
|
||||
// Add all files to affectedFilesPendingEmit since emit changed
|
||||
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.path, BuilderFileEmit.Full));
|
||||
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
|
||||
Debug.assert(state.seenAffectedFiles === undefined);
|
||||
state.seenAffectedFiles = createMap<true>();
|
||||
}
|
||||
@@ -321,7 +321,7 @@ namespace ts {
|
||||
* Verifies that source file is ok to be used in calls that arent handled by next
|
||||
*/
|
||||
function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) {
|
||||
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.path));
|
||||
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,7 +338,7 @@ namespace ts {
|
||||
let affectedFilesIndex = state.affectedFilesIndex!; // TODO: GH#18217
|
||||
while (affectedFilesIndex < affectedFiles.length) {
|
||||
const affectedFile = affectedFiles[affectedFilesIndex];
|
||||
if (!seenAffectedFiles.has(affectedFile.path)) {
|
||||
if (!seenAffectedFiles.has(affectedFile.resolvedPath)) {
|
||||
// Set the next affected file as seen and remove the cached semantic diagnostics
|
||||
state.affectedFilesIndex = affectedFilesIndex;
|
||||
handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, computeHash);
|
||||
@@ -395,8 +395,8 @@ namespace ts {
|
||||
for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) {
|
||||
const affectedFile = Debug.assertDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]);
|
||||
if (affectedFile) {
|
||||
const seenKind = seenEmittedFiles.get(affectedFile.path);
|
||||
const emitKind = Debug.assertDefined(Debug.assertDefined(state.affectedFilesPendingEmitKind).get(affectedFile.path));
|
||||
const seenKind = seenEmittedFiles.get(affectedFile.resolvedPath);
|
||||
const emitKind = Debug.assertDefined(Debug.assertDefined(state.affectedFilesPendingEmitKind).get(affectedFile.resolvedPath));
|
||||
if (seenKind === undefined || seenKind < emitKind) {
|
||||
// emit this file
|
||||
state.affectedFilesPendingEmitIndex = i;
|
||||
@@ -416,7 +416,7 @@ namespace ts {
|
||||
* 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) {
|
||||
removeSemanticDiagnosticsOf(state, affectedFile.path);
|
||||
removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath);
|
||||
|
||||
// If affected files is everything except default library, then nothing more to do
|
||||
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles) {
|
||||
@@ -427,7 +427,7 @@ namespace ts {
|
||||
forEach(program.getSourceFiles(), f =>
|
||||
program.isSourceFileDefaultLibrary(f) &&
|
||||
!skipTypeChecking(f, options, program) &&
|
||||
removeSemanticDiagnosticsOf(state, f.path)
|
||||
removeSemanticDiagnosticsOf(state, f.resolvedPath)
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -495,17 +495,17 @@ namespace ts {
|
||||
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.changedFilesSet.has(affectedFile.path)) {
|
||||
if (!state.exportedModulesMap || !state.changedFilesSet.has(affectedFile.resolvedPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isChangedSignagure(state, affectedFile.path)) return;
|
||||
if (!isChangedSignagure(state, affectedFile.resolvedPath)) return;
|
||||
|
||||
// Since isolated modules dont change js files, files affected by change in signature is itself
|
||||
// But we need to cleanup semantic diagnostics and queue dts emit for affected files
|
||||
if (state.compilerOptions.isolatedModules) {
|
||||
const seenFileNamesMap = createMap<true>();
|
||||
seenFileNamesMap.set(affectedFile.path, true);
|
||||
seenFileNamesMap.set(affectedFile.resolvedPath, true);
|
||||
const queue = BuilderState.getReferencedByPaths(state, affectedFile.resolvedPath);
|
||||
while (queue.length > 0) {
|
||||
const currentPath = queue.pop()!;
|
||||
@@ -526,7 +526,7 @@ namespace ts {
|
||||
// If exported modules has path, all files referencing file exported from are affected
|
||||
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
|
||||
exportedModules &&
|
||||
exportedModules.has(affectedFile.path) &&
|
||||
exportedModules.has(affectedFile.resolvedPath) &&
|
||||
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||
)) {
|
||||
return;
|
||||
@@ -535,7 +535,7 @@ namespace ts {
|
||||
// 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) &&
|
||||
exportedModules.has(affectedFile.resolvedPath) &&
|
||||
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
|
||||
);
|
||||
}
|
||||
@@ -610,9 +610,9 @@ namespace ts {
|
||||
state.programEmitComplete = true;
|
||||
}
|
||||
else {
|
||||
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
|
||||
state.seenAffectedFiles!.set((affected as SourceFile).resolvedPath, true);
|
||||
if (emitKind !== undefined) {
|
||||
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, emitKind);
|
||||
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).resolvedPath, emitKind);
|
||||
}
|
||||
if (isPendingEmit) {
|
||||
state.affectedFilesPendingEmitIndex!++;
|
||||
@@ -662,7 +662,7 @@ namespace ts {
|
||||
* Note that it is assumed that when asked about binder and checker diagnostics, the file has been taken out of affected files/changed file set
|
||||
*/
|
||||
function getBinderAndCheckerDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
|
||||
const path = sourceFile.path;
|
||||
const path = sourceFile.resolvedPath;
|
||||
if (state.semanticDiagnosticsPerFile) {
|
||||
const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path);
|
||||
// Report the bind and check diagnostics from the cache if we already have those diagnostics present
|
||||
@@ -806,7 +806,7 @@ namespace ts {
|
||||
const { file } = diagnostic;
|
||||
return {
|
||||
...diagnostic,
|
||||
file: file ? relativeToBuildInfo(file.path) : undefined
|
||||
file: file ? relativeToBuildInfo(file.resolvedPath) : undefined
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1032,7 +1032,7 @@ namespace ts {
|
||||
|
||||
// Add file to affected file pending emit to handle for later emit time
|
||||
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
|
||||
addToAffectedFilesPendingEmit(state, (affected as SourceFile).path, BuilderFileEmit.Full);
|
||||
addToAffectedFilesPendingEmit(state, (affected as SourceFile).resolvedPath, BuilderFileEmit.Full);
|
||||
}
|
||||
|
||||
// Get diagnostics for the affected file if its not ignored
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const sourceFileDirectory = getDirectoryPath(sourceFile.path);
|
||||
const sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath);
|
||||
// Handle triple slash references
|
||||
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
|
||||
for (const referencedFile of sourceFile.referencedFiles) {
|
||||
@@ -211,21 +211,21 @@ namespace ts {
|
||||
// Create the reference map, and set the file infos
|
||||
for (const sourceFile of newProgram.getSourceFiles()) {
|
||||
const version = Debug.assertDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set");
|
||||
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined;
|
||||
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath) : undefined;
|
||||
if (referencedMap) {
|
||||
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
|
||||
if (newReferences) {
|
||||
referencedMap.set(sourceFile.path, newReferences);
|
||||
referencedMap.set(sourceFile.resolvedPath, newReferences);
|
||||
}
|
||||
// Copy old visible to outside files map
|
||||
if (useOldState) {
|
||||
const exportedModules = oldState!.exportedModulesMap!.get(sourceFile.path);
|
||||
const exportedModules = oldState!.exportedModulesMap!.get(sourceFile.resolvedPath);
|
||||
if (exportedModules) {
|
||||
exportedModulesMap!.set(sourceFile.path, exportedModules);
|
||||
exportedModulesMap!.set(sourceFile.resolvedPath, exportedModules);
|
||||
}
|
||||
}
|
||||
}
|
||||
fileInfos.set(sourceFile.path, { version, signature: oldInfo && oldInfo.signature });
|
||||
fileInfos.set(sourceFile.resolvedPath, { version, signature: oldInfo && oldInfo.signature });
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -306,11 +306,11 @@ namespace ts {
|
||||
Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state");
|
||||
|
||||
// If we have cached the result for this file, that means hence forth we should assume file shape is uptodate
|
||||
if (state.hasCalledUpdateShapeSignature.has(sourceFile.path) || cacheToUpdateSignature.has(sourceFile.path)) {
|
||||
if (state.hasCalledUpdateShapeSignature.has(sourceFile.resolvedPath) || cacheToUpdateSignature.has(sourceFile.resolvedPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const info = state.fileInfos.get(sourceFile.path);
|
||||
const info = state.fileInfos.get(sourceFile.resolvedPath);
|
||||
if (!info) return Debug.fail();
|
||||
|
||||
const prevSignature = info.signature;
|
||||
@@ -319,8 +319,8 @@ namespace ts {
|
||||
latestSignature = sourceFile.version;
|
||||
if (exportedModulesMapCache && latestSignature !== prevSignature) {
|
||||
// All the references in this file are exported
|
||||
const references = state.referencedMap ? state.referencedMap.get(sourceFile.path) : undefined;
|
||||
exportedModulesMapCache.set(sourceFile.path, references || false);
|
||||
const references = state.referencedMap ? state.referencedMap.get(sourceFile.resolvedPath) : undefined;
|
||||
exportedModulesMapCache.set(sourceFile.resolvedPath, references || false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -348,7 +348,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
}
|
||||
cacheToUpdateSignature.set(sourceFile.path, latestSignature);
|
||||
cacheToUpdateSignature.set(sourceFile.resolvedPath, latestSignature);
|
||||
|
||||
return !prevSignature || latestSignature !== prevSignature;
|
||||
}
|
||||
@@ -358,13 +358,13 @@ namespace ts {
|
||||
*/
|
||||
function updateExportedModules(sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, exportedModulesMapCache: ComputingExportedModulesMap) {
|
||||
if (!exportedModulesFromDeclarationEmit) {
|
||||
exportedModulesMapCache.set(sourceFile.path, false);
|
||||
exportedModulesMapCache.set(sourceFile.resolvedPath, false);
|
||||
return;
|
||||
}
|
||||
|
||||
let exportedModules: Map<true> | undefined;
|
||||
exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFileFromImportedModuleSymbol(symbol)));
|
||||
exportedModulesMapCache.set(sourceFile.path, exportedModules || false);
|
||||
exportedModulesMapCache.set(sourceFile.resolvedPath, exportedModules || false);
|
||||
|
||||
function addExportedModule(exportedModulePath: Path | undefined) {
|
||||
if (exportedModulePath) {
|
||||
@@ -411,7 +411,7 @@ namespace ts {
|
||||
|
||||
// Get the references, traversing deep from the referenceMap
|
||||
const seenMap = createMap<true>();
|
||||
const queue = [sourceFile.path];
|
||||
const queue = [sourceFile.resolvedPath];
|
||||
while (queue.length) {
|
||||
const path = queue.pop()!;
|
||||
if (!seenMap.has(path)) {
|
||||
@@ -541,7 +541,7 @@ namespace ts {
|
||||
const seenFileNamesMap = createMap<SourceFile>();
|
||||
|
||||
// Start with the paths this file was referenced by
|
||||
seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape);
|
||||
seenFileNamesMap.set(sourceFileWithUpdatedShape.resolvedPath, sourceFileWithUpdatedShape);
|
||||
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.resolvedPath);
|
||||
while (queue.length > 0) {
|
||||
const currentPath = queue.pop()!;
|
||||
|
||||
@@ -810,7 +810,7 @@ export function gfoo() {
|
||||
[aDts, [aDts]],
|
||||
[bDts, [bDts, aDts]],
|
||||
[refs.path, [refs.path]],
|
||||
[cTs.path, [cTs.path, refs.path, bDts]]
|
||||
[cTs.path, [cTs.path, refs.path, bDts, aDts]]
|
||||
];
|
||||
|
||||
function createSolutionAndWatchMode() {
|
||||
@@ -965,7 +965,7 @@ export function gfoo() {
|
||||
[aDts, [aDts]],
|
||||
[bDts, [bDts, aDts]],
|
||||
[nrefs.path, [nrefs.path]],
|
||||
[cTs.path, [cTs.path, nrefs.path, bDts]]
|
||||
[cTs.path, [cTs.path, nrefs.path, bDts, aDts]]
|
||||
],
|
||||
// revert the update
|
||||
revert: host => host.writeFile(cTsconfig.path, cTsconfig.content),
|
||||
@@ -1001,7 +1001,7 @@ export function gfoo() {
|
||||
[nrefs.path, [nrefs.path]],
|
||||
[bDts, [bDts, nrefs.path]],
|
||||
[refs.path, [refs.path]],
|
||||
[cTs.path, [cTs.path, refs.path, bDts]],
|
||||
[cTs.path, [cTs.path, refs.path, bDts, nrefs.path]],
|
||||
],
|
||||
// revert the update
|
||||
revert: host => host.writeFile(bTsconfig.path, bTsconfig.content),
|
||||
@@ -1055,7 +1055,7 @@ export function gfoo() {
|
||||
[aTs.path, [aTs.path]],
|
||||
[bDts, [bDts, aTs.path]],
|
||||
[refs.path, [refs.path]],
|
||||
[cTs.path, [cTs.path, refs.path, bDts]],
|
||||
[cTs.path, [cTs.path, refs.path, bDts, aTs.path]],
|
||||
],
|
||||
// revert the update
|
||||
revert: host => host.writeFile(aTsconfig.path, aTsconfig.content),
|
||||
@@ -1093,7 +1093,7 @@ export function gfoo() {
|
||||
[aDts, [aDts]],
|
||||
[bDts, [bDts, aDts]],
|
||||
[refs.path, [refs.path]],
|
||||
[cTsFile.path, [cTsFile.path, refs.path, bDts]]
|
||||
[cTsFile.path, [cTsFile.path, refs.path, bDts, aDts]]
|
||||
];
|
||||
function getOutputFileStamps(host: TsBuildWatchSystem) {
|
||||
return expectedFiles.map(file => transformOutputToOutputFileStamp(file, host));
|
||||
@@ -1246,4 +1246,44 @@ const a = {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: watchMode:: with reexport when referenced project reexports definitions from another file", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "reexport",
|
||||
subScenario: "Reports errors correctly",
|
||||
commandLineArgs: ["-b", "-w", "-verbose", "src"],
|
||||
sys: () => createWatchedSystem(
|
||||
[
|
||||
...[
|
||||
"src/tsconfig.json",
|
||||
"src/main/tsconfig.json", "src/main/index.ts",
|
||||
"src/pure/tsconfig.json", "src/pure/index.ts", "src/pure/session.ts"
|
||||
]
|
||||
.map(f => getFileFromProject("reexport", f)),
|
||||
{ path: libFile.path, content: libContent }
|
||||
],
|
||||
{ currentDirectory: `${projectsLocation}/reexport` }
|
||||
),
|
||||
changes: [
|
||||
sys => {
|
||||
const content = sys.readFile(`${projectsLocation}/reexport/src/pure/session.ts`)!;
|
||||
sys.writeFile(`${projectsLocation}/reexport/src/pure/session.ts`, content.replace("// ", ""));
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src/pure
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src/main
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
return "Introduce error";
|
||||
},
|
||||
sys => {
|
||||
const content = sys.readFile(`${projectsLocation}/reexport/src/pure/session.ts`)!;
|
||||
sys.writeFile(`${projectsLocation}/reexport/src/pure/session.ts`, content.replace("bar: ", "// bar: "));
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src/pure
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src/main
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // build src
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
return "Fix error";
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ namespace ts.tscWatch {
|
||||
if (state.semanticDiagnosticsPerFile?.size) {
|
||||
baseline.push("Semantic diagnostics in builder refreshed for::");
|
||||
for (const file of program.getSourceFiles()) {
|
||||
if (!state.semanticDiagnosticsFromOldState || !state.semanticDiagnosticsFromOldState.has(file.path)) {
|
||||
if (!state.semanticDiagnosticsFromOldState || !state.semanticDiagnosticsFromOldState.has(file.resolvedPath)) {
|
||||
baseline.push(file.fileName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user