Use resolvedPath consistently in the builder (#35757)

* Add baseline for #35468

* Use resolvedPath consistently in the builder
Fixes #35468
This commit is contained in:
Sheetal Nandi
2019-12-19 10:10:17 -08:00
committed by GitHub
parent 5d3284032b
commit ec84392f2e
46 changed files with 1073 additions and 520 deletions

View File

@@ -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

View File

@@ -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()!;

View File

@@ -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";
}
]
});
});
}

View File

@@ -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);
}
}