Skip to content

Commit

Permalink
Handle buildInfo and tsc --b scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed May 17, 2024
1 parent f28002d commit a865de4
Show file tree
Hide file tree
Showing 9 changed files with 568 additions and 445 deletions.
37 changes: 34 additions & 3 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
isNumber,
isString,
map,
mapDefinedIterator,

Check warning on line 61 in src/compiler/builder.ts

View workflow job for this annotation

GitHub Actions / lint

'mapDefinedIterator' is defined but never used. Allowed unused vars must match /^(_+$|_[^_])/u
maybeBind,
noop,
notImplemented,
Expand Down Expand Up @@ -990,10 +991,13 @@ export type ProgramBuildInfoRootStartEnd = [start: ProgramBuildInfoFileId, end:
*/
export type ProgramBuildInfoRoot = ProgramBuildInfoRootStartEnd | ProgramBuildInfoFileId;
/** @internal */
export type ProgramBuildInfoResolvedRoot = [resolved: ProgramBuildInfoFileId, root: ProgramBuildInfoFileId];
/** @internal */
export interface ProgramMultiFileEmitBuildInfo {
fileNames: readonly string[];
fileInfos: readonly ProgramMultiFileEmitBuildInfoFileInfo[];
root: readonly ProgramBuildInfoRoot[];
resolvedRoot: readonly ProgramBuildInfoResolvedRoot[] | undefined;
options: CompilerOptions | undefined;
fileIdsList: readonly (readonly ProgramBuildInfoFileId[])[] | undefined;
referencedMap: ProgramBuildInfoReferencedMap | undefined;
Expand Down Expand Up @@ -1023,6 +1027,7 @@ export interface ProgramBundleEmitBuildInfo {
fileNames: readonly string[];
fileInfos: readonly ProgramBundleEmitBuildInfoFileInfo[];
root: readonly ProgramBuildInfoRoot[];
resolvedRoot: readonly ProgramBuildInfoResolvedRoot[] | undefined;
options: CompilerOptions | undefined;
outSignature: EmitSignature | undefined;
latestChangedDtsFile: string | undefined;
Expand All @@ -1047,6 +1052,7 @@ function getBuildInfo(state: BuilderProgramState): BuildInfo {
const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : undefined;
const fileNames: string[] = [];
const fileNameToFileId = new Map<string, ProgramBuildInfoFileId>();
const rootFileNames = new Set(state.program!.getRootFileNames().map(f => toPath(f, currentDirectory, state.program!.getCanonicalFileName)));
const root: ProgramBuildInfoRoot[] = [];
if (state.compilerOptions.outFile) {
// Copy all fileInfo, version and impliedFormat
Expand All @@ -1063,6 +1069,7 @@ function getBuildInfo(state: BuilderProgramState): BuildInfo {
fileNames,
fileInfos,
root,
resolvedRoot: toResolvedRoot(),
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions),
outSignature: state.outSignature,
latestChangedDtsFile,
Expand Down Expand Up @@ -1155,6 +1162,7 @@ function getBuildInfo(state: BuilderProgramState): BuildInfo {
fileNames,
fileInfos,
root,
resolvedRoot: toResolvedRoot(),
options: convertToProgramBuildInfoCompilerOptions(state.compilerOptions),
fileIdsList,
referencedMap,
Expand Down Expand Up @@ -1214,6 +1222,17 @@ function getBuildInfo(state: BuilderProgramState): BuildInfo {
return root.length = root.length - 1;
}

function toResolvedRoot(): ProgramBuildInfoResolvedRoot[] | undefined {
let result: ProgramBuildInfoResolvedRoot[] | undefined;
rootFileNames.forEach(path => {
const file = state.program!.getSourceFileByPath(path);
if (file && path !== file.resolvedPath) {
(result ??= []).push([toFileId(file.resolvedPath), toFileId(path)]);
}
});
return result;
}

/**
* @param optionKey key of CommandLineOption to use to determine if the option should be serialized in tsbuildinfo
*/
Expand Down Expand Up @@ -1909,7 +1928,9 @@ export function getBuildInfoFileVersionMap(
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
const fileInfos = new Map<Path, string>();
let rootIndex = 0;
const roots: Path[] = [];
// Root name to resolved
const roots = new Map<Path, Path | undefined>();
const resolvedRoots = new Map(program.resolvedRoot);
program.fileInfos.forEach((fileInfo, index) => {
const path = toPath(program.fileNames[index], buildInfoDirectory, getCanonicalFileName);
const version = isString(fileInfo) ? fileInfo : fileInfo.version;
Expand All @@ -1919,17 +1940,27 @@ export function getBuildInfoFileVersionMap(
const fileId = (index + 1) as ProgramBuildInfoFileId;
if (isArray(current)) {
if (current[0] <= fileId && fileId <= current[1]) {
roots.push(path);
addRoot(fileId, path);
if (current[1] === fileId) rootIndex++;
}
}
else if (current === fileId) {
roots.push(path);
addRoot(fileId, path);
rootIndex++;
}
}
});
return { fileInfos, roots };

function addRoot(fileId: ProgramBuildInfoFileId, path: Path) {
const root = resolvedRoots.get(fileId);
if (root) {
roots.set(toPath(program.fileNames[root - 1], buildInfoDirectory, getCanonicalFileName), path);
}
else {
roots.set(path, undefined);
}
}
}

/** @internal */
Expand Down
29 changes: 17 additions & 12 deletions src/compiler/tsbuildPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
findIndex,
flattenDiagnosticMessageText,
forEach,
forEachEntry,
forEachKey,
ForegroundColorEscapeSequences,
formatColorAndReset,
Expand Down Expand Up @@ -1734,15 +1735,17 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
};
}

const inputPath = buildInfoProgram ? toPath(state, inputFile) : undefined;
// If an buildInfo is older than the newest input, we can stop checking
if (buildInfoTime && buildInfoTime < inputTime) {
let version: string | undefined;
let currentVersion: string | undefined;
if (buildInfoProgram) {
// Read files and see if they are same, read is anyways cached
if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host);
version = buildInfoVersionMap.fileInfos.get(toPath(state, inputFile));
const text = version ? state.readFileWithCache(inputFile) : undefined;
const resolvedInputPath = buildInfoVersionMap.roots.get(inputPath!);
version = buildInfoVersionMap.fileInfos.get(resolvedInputPath ?? inputPath!);
const text = version ? state.readFileWithCache(resolvedInputPath ?? inputFile) : undefined;
currentVersion = text !== undefined ? getSourceFileVersionAsHashFromText(host, text) : undefined;
if (version && version === currentVersion) pseudoInputUpToDate = true;
}
Expand All @@ -1761,20 +1764,22 @@ function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilde
newestInputFileTime = inputTime;
}

if (buildInfoProgram) seenRoots.add(toPath(state, inputFile));
if (buildInfoProgram) seenRoots.add(inputPath!);
}

if (buildInfoProgram) {
if (!buildInfoVersionMap) buildInfoVersionMap = getBuildInfoFileVersionMap(buildInfoProgram, buildInfoPath!, host);
for (const existingRoot of buildInfoVersionMap.roots) {
if (!seenRoots.has(existingRoot)) {
// File was root file when project was built but its not any more
return {
type: UpToDateStatusType.OutOfDateRoots,
buildInfoFile: buildInfoPath!,
inputFile: existingRoot,
};
}
const existingRoot = forEachEntry(
buildInfoVersionMap.roots,
// File was root file when project was built but its not any more
(_resolved, existingRoot) => !seenRoots.has(existingRoot) ? existingRoot : undefined,
);
if (existingRoot) {
return {
type: UpToDateStatusType.OutOfDateRoots,
buildInfoFile: buildInfoPath!,
inputFile: existingRoot,
};
}
}

Expand Down
17 changes: 15 additions & 2 deletions src/testRunner/unittests/helpers/baseline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,16 @@ export type ReadableProgramBuildInfoFileInfo<T> = Omit<ts.BuilderState.FileInfo,
export type ReadableProgramBuildInfoRoot =
| [original: ts.ProgramBuildInfoFileId, readable: string]
| [original: ts.ProgramBuildInfoRootStartEnd, readable: readonly string[]];
export type ReadableProgramMultiFileEmitBuildInfo = Omit<ts.ProgramMultiFileEmitBuildInfo, "fileIdsList" | "fileInfos" | "root" | "referencedMap" | "semanticDiagnosticsPerFile" | "emitDiagnosticsPerFile" | "affectedFilesPendingEmit" | "changeFileSet" | "emitSignatures"> & {

export type ReadableProgramBuildInfoResolvedRoot = [
original: ts.ProgramBuildInfoResolvedRoot,
readable: [resolved: string, root: string],
];
export type ReadableProgramMultiFileEmitBuildInfo = Omit<ts.ProgramMultiFileEmitBuildInfo, "fileIdsList" | "fileInfos" | "root" | "resolvedRoot" | "referencedMap" | "semanticDiagnosticsPerFile" | "emitDiagnosticsPerFile" | "affectedFilesPendingEmit" | "changeFileSet" | "emitSignatures"> & {
fileNamesList: readonly (readonly string[])[] | undefined;
fileInfos: ts.MapLike<ReadableProgramBuildInfoFileInfo<ts.ProgramMultiFileEmitBuildInfoFileInfo>>;
root: readonly ReadableProgramBuildInfoRoot[];
resolvedRoot: readonly ReadableProgramBuildInfoResolvedRoot[] | undefined;
referencedMap: ts.MapLike<string[]> | undefined;
semanticDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined;
emitDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined;
Expand All @@ -153,9 +159,10 @@ export type ReadableProgramMultiFileEmitBuildInfo = Omit<ts.ProgramMultiFileEmit
emitSignatures: readonly ReadableProgramBuildInfoEmitSignature[] | undefined;
};
export type ReadableProgramBuildInfoBundlePendingEmit = [emitKind: ReadableBuilderFileEmit, original: ts.ProgramBuildInfoBundlePendingEmit];
export type ReadableProgramBundleEmitBuildInfo = Omit<ts.ProgramBundleEmitBuildInfo, "fileInfos" | "root" | "pendingEmit"> & {
export type ReadableProgramBundleEmitBuildInfo = Omit<ts.ProgramBundleEmitBuildInfo, "fileInfos" | "root" | "resolvedRoot" | "pendingEmit"> & {
fileInfos: ts.MapLike<string | ReadableProgramBuildInfoFileInfo<ts.BuilderState.FileInfo>>;
root: readonly ReadableProgramBuildInfoRoot[];
resolvedRoot: readonly ReadableProgramBuildInfoResolvedRoot[] | undefined;
pendingEmit: ReadableProgramBuildInfoBundlePendingEmit | undefined;
};

Expand All @@ -180,6 +187,7 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string,
...buildInfo.program,
fileInfos,
root: buildInfo.program.root.map(toReadableProgramBuildInfoRoot),
resolvedRoot: buildInfo.program.resolvedRoot?.map(toReadableProgramBuildInfoResolvedRoot),
pendingEmit: pendingEmit === undefined ?
undefined :
[
Expand All @@ -198,6 +206,7 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string,
fileNamesList,
fileInfos: buildInfo.program.fileInfos ? fileInfos : undefined!,
root: buildInfo.program.root.map(toReadableProgramBuildInfoRoot),
resolvedRoot: buildInfo.program.resolvedRoot?.map(toReadableProgramBuildInfoResolvedRoot),
options: buildInfo.program.options,
referencedMap: toMapOfReferencedSet(buildInfo.program.referencedMap),
semanticDiagnosticsPerFile: toReadableProgramBuildInfoDiagnosticsPerFile(buildInfo.program.semanticDiagnosticsPerFile),
Expand Down Expand Up @@ -245,6 +254,10 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string,
return [original, readable];
}

function toReadableProgramBuildInfoResolvedRoot(original: ts.ProgramBuildInfoResolvedRoot): ReadableProgramBuildInfoResolvedRoot {
return [original, [toFileName(original[0]), toFileName(original[1])]];
}

function toMapOfReferencedSet(referenceMap: ts.ProgramBuildInfoReferencedMap | undefined): ts.MapLike<string[]> | undefined {
if (!referenceMap) return undefined;
const result: ts.MapLike<string[]> = {};
Expand Down
Loading

0 comments on commit a865de4

Please sign in to comment.