Skip to content

Commit ec84392

Browse files
authored
Use resolvedPath consistently in the builder (microsoft#35757)
* Add baseline for microsoft#35468 * Use resolvedPath consistently in the builder Fixes microsoft#35468
1 parent 5d32840 commit ec84392

File tree

46 files changed

+1065
-512
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1065
-512
lines changed

src/compiler/builder.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ namespace ts {
246246

247247
if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
248248
// Add all files to affectedFilesPendingEmit since emit changed
249-
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.path, BuilderFileEmit.Full));
249+
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
250250
Debug.assert(state.seenAffectedFiles === undefined);
251251
state.seenAffectedFiles = createMap<true>();
252252
}
@@ -321,7 +321,7 @@ namespace ts {
321321
* Verifies that source file is ok to be used in calls that arent handled by next
322322
*/
323323
function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) {
324-
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.path));
324+
Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath));
325325
}
326326

327327
/**
@@ -338,7 +338,7 @@ namespace ts {
338338
let affectedFilesIndex = state.affectedFilesIndex!; // TODO: GH#18217
339339
while (affectedFilesIndex < affectedFiles.length) {
340340
const affectedFile = affectedFiles[affectedFilesIndex];
341-
if (!seenAffectedFiles.has(affectedFile.path)) {
341+
if (!seenAffectedFiles.has(affectedFile.resolvedPath)) {
342342
// Set the next affected file as seen and remove the cached semantic diagnostics
343343
state.affectedFilesIndex = affectedFilesIndex;
344344
handleDtsMayChangeOfAffectedFile(state, affectedFile, cancellationToken, computeHash);
@@ -395,8 +395,8 @@ namespace ts {
395395
for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) {
396396
const affectedFile = Debug.assertDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]);
397397
if (affectedFile) {
398-
const seenKind = seenEmittedFiles.get(affectedFile.path);
399-
const emitKind = Debug.assertDefined(Debug.assertDefined(state.affectedFilesPendingEmitKind).get(affectedFile.path));
398+
const seenKind = seenEmittedFiles.get(affectedFile.resolvedPath);
399+
const emitKind = Debug.assertDefined(Debug.assertDefined(state.affectedFilesPendingEmitKind).get(affectedFile.resolvedPath));
400400
if (seenKind === undefined || seenKind < emitKind) {
401401
// emit this file
402402
state.affectedFilesPendingEmitIndex = i;
@@ -416,7 +416,7 @@ namespace ts {
416416
* This is because even though js emit doesnt change, dts emit / type used can change resulting in need for dts emit and js change
417417
*/
418418
function handleDtsMayChangeOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash) {
419-
removeSemanticDiagnosticsOf(state, affectedFile.path);
419+
removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath);
420420

421421
// If affected files is everything except default library, then nothing more to do
422422
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles) {
@@ -427,7 +427,7 @@ namespace ts {
427427
forEach(program.getSourceFiles(), f =>
428428
program.isSourceFileDefaultLibrary(f) &&
429429
!skipTypeChecking(f, options, program) &&
430-
removeSemanticDiagnosticsOf(state, f.path)
430+
removeSemanticDiagnosticsOf(state, f.resolvedPath)
431431
);
432432
}
433433
return;
@@ -495,17 +495,17 @@ namespace ts {
495495
function forEachReferencingModulesOfExportOfAffectedFile(state: BuilderProgramState, affectedFile: SourceFile, fn: (state: BuilderProgramState, filePath: Path) => boolean) {
496496
// If there was change in signature (dts output) for the changed file,
497497
// then only we need to handle pending file emit
498-
if (!state.exportedModulesMap || !state.changedFilesSet.has(affectedFile.path)) {
498+
if (!state.exportedModulesMap || !state.changedFilesSet.has(affectedFile.resolvedPath)) {
499499
return;
500500
}
501501

502-
if (!isChangedSignagure(state, affectedFile.path)) return;
502+
if (!isChangedSignagure(state, affectedFile.resolvedPath)) return;
503503

504504
// Since isolated modules dont change js files, files affected by change in signature is itself
505505
// But we need to cleanup semantic diagnostics and queue dts emit for affected files
506506
if (state.compilerOptions.isolatedModules) {
507507
const seenFileNamesMap = createMap<true>();
508-
seenFileNamesMap.set(affectedFile.path, true);
508+
seenFileNamesMap.set(affectedFile.resolvedPath, true);
509509
const queue = BuilderState.getReferencedByPaths(state, affectedFile.resolvedPath);
510510
while (queue.length > 0) {
511511
const currentPath = queue.pop()!;
@@ -526,7 +526,7 @@ namespace ts {
526526
// If exported modules has path, all files referencing file exported from are affected
527527
if (forEachEntry(state.currentAffectedFilesExportedModulesMap!, (exportedModules, exportedFromPath) =>
528528
exportedModules &&
529-
exportedModules.has(affectedFile.path) &&
529+
exportedModules.has(affectedFile.resolvedPath) &&
530530
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
531531
)) {
532532
return;
@@ -535,7 +535,7 @@ namespace ts {
535535
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
536536
forEachEntry(state.exportedModulesMap, (exportedModules, exportedFromPath) =>
537537
!state.currentAffectedFilesExportedModulesMap!.has(exportedFromPath) && // If we already iterated this through cache, ignore it
538-
exportedModules.has(affectedFile.path) &&
538+
exportedModules.has(affectedFile.resolvedPath) &&
539539
forEachFilesReferencingPath(state, exportedFromPath as Path, seenFileAndExportsOfFile, fn)
540540
);
541541
}
@@ -610,9 +610,9 @@ namespace ts {
610610
state.programEmitComplete = true;
611611
}
612612
else {
613-
state.seenAffectedFiles!.set((affected as SourceFile).path, true);
613+
state.seenAffectedFiles!.set((affected as SourceFile).resolvedPath, true);
614614
if (emitKind !== undefined) {
615-
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).path, emitKind);
615+
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).resolvedPath, emitKind);
616616
}
617617
if (isPendingEmit) {
618618
state.affectedFilesPendingEmitIndex!++;
@@ -662,7 +662,7 @@ namespace ts {
662662
* 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
663663
*/
664664
function getBinderAndCheckerDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
665-
const path = sourceFile.path;
665+
const path = sourceFile.resolvedPath;
666666
if (state.semanticDiagnosticsPerFile) {
667667
const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path);
668668
// Report the bind and check diagnostics from the cache if we already have those diagnostics present
@@ -806,7 +806,7 @@ namespace ts {
806806
const { file } = diagnostic;
807807
return {
808808
...diagnostic,
809-
file: file ? relativeToBuildInfo(file.path) : undefined
809+
file: file ? relativeToBuildInfo(file.resolvedPath) : undefined
810810
};
811811
}
812812

@@ -1032,7 +1032,7 @@ namespace ts {
10321032

10331033
// Add file to affected file pending emit to handle for later emit time
10341034
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
1035-
addToAffectedFilesPendingEmit(state, (affected as SourceFile).path, BuilderFileEmit.Full);
1035+
addToAffectedFilesPendingEmit(state, (affected as SourceFile).resolvedPath, BuilderFileEmit.Full);
10361036
}
10371037

10381038
// Get diagnostics for the affected file if its not ignored

src/compiler/builderState.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ namespace ts {
128128
}
129129
}
130130

131-
const sourceFileDirectory = getDirectoryPath(sourceFile.path);
131+
const sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath);
132132
// Handle triple slash references
133133
if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) {
134134
for (const referencedFile of sourceFile.referencedFiles) {
@@ -211,21 +211,21 @@ namespace ts {
211211
// Create the reference map, and set the file infos
212212
for (const sourceFile of newProgram.getSourceFiles()) {
213213
const version = Debug.assertDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set");
214-
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.path) : undefined;
214+
const oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath) : undefined;
215215
if (referencedMap) {
216216
const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName);
217217
if (newReferences) {
218-
referencedMap.set(sourceFile.path, newReferences);
218+
referencedMap.set(sourceFile.resolvedPath, newReferences);
219219
}
220220
// Copy old visible to outside files map
221221
if (useOldState) {
222-
const exportedModules = oldState!.exportedModulesMap!.get(sourceFile.path);
222+
const exportedModules = oldState!.exportedModulesMap!.get(sourceFile.resolvedPath);
223223
if (exportedModules) {
224-
exportedModulesMap!.set(sourceFile.path, exportedModules);
224+
exportedModulesMap!.set(sourceFile.resolvedPath, exportedModules);
225225
}
226226
}
227227
}
228-
fileInfos.set(sourceFile.path, { version, signature: oldInfo && oldInfo.signature });
228+
fileInfos.set(sourceFile.resolvedPath, { version, signature: oldInfo && oldInfo.signature });
229229
}
230230

231231
return {
@@ -306,11 +306,11 @@ namespace ts {
306306
Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state");
307307

308308
// If we have cached the result for this file, that means hence forth we should assume file shape is uptodate
309-
if (state.hasCalledUpdateShapeSignature.has(sourceFile.path) || cacheToUpdateSignature.has(sourceFile.path)) {
309+
if (state.hasCalledUpdateShapeSignature.has(sourceFile.resolvedPath) || cacheToUpdateSignature.has(sourceFile.resolvedPath)) {
310310
return false;
311311
}
312312

313-
const info = state.fileInfos.get(sourceFile.path);
313+
const info = state.fileInfos.get(sourceFile.resolvedPath);
314314
if (!info) return Debug.fail();
315315

316316
const prevSignature = info.signature;
@@ -319,8 +319,8 @@ namespace ts {
319319
latestSignature = sourceFile.version;
320320
if (exportedModulesMapCache && latestSignature !== prevSignature) {
321321
// All the references in this file are exported
322-
const references = state.referencedMap ? state.referencedMap.get(sourceFile.path) : undefined;
323-
exportedModulesMapCache.set(sourceFile.path, references || false);
322+
const references = state.referencedMap ? state.referencedMap.get(sourceFile.resolvedPath) : undefined;
323+
exportedModulesMapCache.set(sourceFile.resolvedPath, references || false);
324324
}
325325
}
326326
else {
@@ -348,7 +348,7 @@ namespace ts {
348348
}
349349

350350
}
351-
cacheToUpdateSignature.set(sourceFile.path, latestSignature);
351+
cacheToUpdateSignature.set(sourceFile.resolvedPath, latestSignature);
352352

353353
return !prevSignature || latestSignature !== prevSignature;
354354
}
@@ -358,13 +358,13 @@ namespace ts {
358358
*/
359359
function updateExportedModules(sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, exportedModulesMapCache: ComputingExportedModulesMap) {
360360
if (!exportedModulesFromDeclarationEmit) {
361-
exportedModulesMapCache.set(sourceFile.path, false);
361+
exportedModulesMapCache.set(sourceFile.resolvedPath, false);
362362
return;
363363
}
364364

365365
let exportedModules: Map<true> | undefined;
366366
exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFileFromImportedModuleSymbol(symbol)));
367-
exportedModulesMapCache.set(sourceFile.path, exportedModules || false);
367+
exportedModulesMapCache.set(sourceFile.resolvedPath, exportedModules || false);
368368

369369
function addExportedModule(exportedModulePath: Path | undefined) {
370370
if (exportedModulePath) {
@@ -411,7 +411,7 @@ namespace ts {
411411

412412
// Get the references, traversing deep from the referenceMap
413413
const seenMap = createMap<true>();
414-
const queue = [sourceFile.path];
414+
const queue = [sourceFile.resolvedPath];
415415
while (queue.length) {
416416
const path = queue.pop()!;
417417
if (!seenMap.has(path)) {
@@ -541,7 +541,7 @@ namespace ts {
541541
const seenFileNamesMap = createMap<SourceFile>();
542542

543543
// Start with the paths this file was referenced by
544-
seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape);
544+
seenFileNamesMap.set(sourceFileWithUpdatedShape.resolvedPath, sourceFileWithUpdatedShape);
545545
const queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.resolvedPath);
546546
while (queue.length > 0) {
547547
const currentPath = queue.pop()!;

src/testRunner/unittests/tsbuild/watchMode.ts

+45-5
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ export function gfoo() {
810810
[aDts, [aDts]],
811811
[bDts, [bDts, aDts]],
812812
[refs.path, [refs.path]],
813-
[cTs.path, [cTs.path, refs.path, bDts]]
813+
[cTs.path, [cTs.path, refs.path, bDts, aDts]]
814814
];
815815

816816
function createSolutionAndWatchMode() {
@@ -965,7 +965,7 @@ export function gfoo() {
965965
[aDts, [aDts]],
966966
[bDts, [bDts, aDts]],
967967
[nrefs.path, [nrefs.path]],
968-
[cTs.path, [cTs.path, nrefs.path, bDts]]
968+
[cTs.path, [cTs.path, nrefs.path, bDts, aDts]]
969969
],
970970
// revert the update
971971
revert: host => host.writeFile(cTsconfig.path, cTsconfig.content),
@@ -1001,7 +1001,7 @@ export function gfoo() {
10011001
[nrefs.path, [nrefs.path]],
10021002
[bDts, [bDts, nrefs.path]],
10031003
[refs.path, [refs.path]],
1004-
[cTs.path, [cTs.path, refs.path, bDts]],
1004+
[cTs.path, [cTs.path, refs.path, bDts, nrefs.path]],
10051005
],
10061006
// revert the update
10071007
revert: host => host.writeFile(bTsconfig.path, bTsconfig.content),
@@ -1055,7 +1055,7 @@ export function gfoo() {
10551055
[aTs.path, [aTs.path]],
10561056
[bDts, [bDts, aTs.path]],
10571057
[refs.path, [refs.path]],
1058-
[cTs.path, [cTs.path, refs.path, bDts]],
1058+
[cTs.path, [cTs.path, refs.path, bDts, aTs.path]],
10591059
],
10601060
// revert the update
10611061
revert: host => host.writeFile(aTsconfig.path, aTsconfig.content),
@@ -1093,7 +1093,7 @@ export function gfoo() {
10931093
[aDts, [aDts]],
10941094
[bDts, [bDts, aDts]],
10951095
[refs.path, [refs.path]],
1096-
[cTsFile.path, [cTsFile.path, refs.path, bDts]]
1096+
[cTsFile.path, [cTsFile.path, refs.path, bDts, aDts]]
10971097
];
10981098
function getOutputFileStamps(host: TsBuildWatchSystem) {
10991099
return expectedFiles.map(file => transformOutputToOutputFileStamp(file, host));
@@ -1246,4 +1246,44 @@ const a = {
12461246
]
12471247
});
12481248
});
1249+
1250+
describe("unittests:: tsbuild:: watchMode:: with reexport when referenced project reexports definitions from another file", () => {
1251+
verifyTscWatch({
1252+
scenario: "reexport",
1253+
subScenario: "Reports errors correctly",
1254+
commandLineArgs: ["-b", "-w", "-verbose", "src"],
1255+
sys: () => createWatchedSystem(
1256+
[
1257+
...[
1258+
"src/tsconfig.json",
1259+
"src/main/tsconfig.json", "src/main/index.ts",
1260+
"src/pure/tsconfig.json", "src/pure/index.ts", "src/pure/session.ts"
1261+
]
1262+
.map(f => getFileFromProject("reexport", f)),
1263+
{ path: libFile.path, content: libContent }
1264+
],
1265+
{ currentDirectory: `${projectsLocation}/reexport` }
1266+
),
1267+
changes: [
1268+
sys => {
1269+
const content = sys.readFile(`${projectsLocation}/reexport/src/pure/session.ts`)!;
1270+
sys.writeFile(`${projectsLocation}/reexport/src/pure/session.ts`, content.replace("// ", ""));
1271+
sys.checkTimeoutQueueLengthAndRun(1); // build src/pure
1272+
sys.checkTimeoutQueueLengthAndRun(1); // build src/main
1273+
sys.checkTimeoutQueueLengthAndRun(1); // build src
1274+
sys.checkTimeoutQueueLength(0);
1275+
return "Introduce error";
1276+
},
1277+
sys => {
1278+
const content = sys.readFile(`${projectsLocation}/reexport/src/pure/session.ts`)!;
1279+
sys.writeFile(`${projectsLocation}/reexport/src/pure/session.ts`, content.replace("bar: ", "// bar: "));
1280+
sys.checkTimeoutQueueLengthAndRun(1); // build src/pure
1281+
sys.checkTimeoutQueueLengthAndRun(1); // build src/main
1282+
sys.checkTimeoutQueueLengthAndRun(1); // build src
1283+
sys.checkTimeoutQueueLength(0);
1284+
return "Fix error";
1285+
}
1286+
]
1287+
});
1288+
});
12491289
}

0 commit comments

Comments
 (0)