Skip to content

Commit d2240a4

Browse files
committed
Ger rid of unnecessary upto date host and functions pulled out
1 parent 17ee923 commit d2240a4

File tree

2 files changed

+181
-202
lines changed

2 files changed

+181
-202
lines changed

src/compiler/tsbuild.ts

Lines changed: 181 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -520,16 +520,6 @@ namespace ts {
520520
let context = createBuildContext(defaultOptions);
521521

522522
const existingWatchersForWildcards = createMap<WildcardDirectoryWatcher>();
523-
524-
const upToDateHost: UpToDateHost = {
525-
fileExists: fileName => compilerHost.fileExists(fileName),
526-
getModifiedTime: fileName => compilerHost.getModifiedTime!(fileName),
527-
getUnchangedTime: fileName => context.unchangedOutputs.getValueOrUndefined(fileName),
528-
getLastStatus: fileName => context.projectStatus.getValueOrUndefined(fileName),
529-
setLastStatus: (fileName, status) => context.projectStatus.setValue(fileName, status),
530-
parseConfigFile: configFilePath => configFileCache.parseConfigFile(configFilePath)
531-
};
532-
533523
return {
534524
buildAllProjects,
535525
getUpToDateStatus,
@@ -611,7 +601,180 @@ namespace ts {
611601
}
612602

613603
function getUpToDateStatus(project: ParsedCommandLine | undefined): UpToDateStatus {
614-
return ts.getUpToDateStatus(upToDateHost, project);
604+
if (project === undefined) {
605+
return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
606+
}
607+
608+
const prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath!);
609+
if (prior !== undefined) {
610+
return prior;
611+
}
612+
613+
const actual = getUpToDateStatusWorker(project);
614+
context.projectStatus.setValue(project.options.configFilePath!, actual);
615+
return actual;
616+
}
617+
618+
function getUpToDateStatusWorker(project: ParsedCommandLine): UpToDateStatus {
619+
let newestInputFileName: string = undefined!;
620+
let newestInputFileTime = minimumDate;
621+
// Get timestamps of input files
622+
for (const inputFile of project.fileNames) {
623+
if (!compilerHost.fileExists(inputFile)) {
624+
return {
625+
type: UpToDateStatusType.Unbuildable,
626+
reason: `${inputFile} does not exist`
627+
};
628+
}
629+
630+
const inputTime = compilerHost.getModifiedTime!(inputFile) || missingFileModifiedTime;
631+
if (inputTime > newestInputFileTime) {
632+
newestInputFileName = inputFile;
633+
newestInputFileTime = inputTime;
634+
}
635+
}
636+
637+
// Collect the expected outputs of this project
638+
const outputs = getAllProjectOutputs(project);
639+
640+
if (outputs.length === 0) {
641+
return {
642+
type: UpToDateStatusType.ContainerOnly
643+
};
644+
}
645+
646+
// Now see if all outputs are newer than the newest input
647+
let oldestOutputFileName = "(none)";
648+
let oldestOutputFileTime = maximumDate;
649+
let newestOutputFileName = "(none)";
650+
let newestOutputFileTime = minimumDate;
651+
let missingOutputFileName: string | undefined;
652+
let newestDeclarationFileContentChangedTime = minimumDate;
653+
let isOutOfDateWithInputs = false;
654+
for (const output of outputs) {
655+
// Output is missing; can stop checking
656+
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
657+
if (!compilerHost.fileExists(output)) {
658+
missingOutputFileName = output;
659+
break;
660+
}
661+
662+
const outputTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime;
663+
if (outputTime < oldestOutputFileTime) {
664+
oldestOutputFileTime = outputTime;
665+
oldestOutputFileName = output;
666+
}
667+
668+
// If an output is older than the newest input, we can stop checking
669+
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
670+
if (outputTime < newestInputFileTime) {
671+
isOutOfDateWithInputs = true;
672+
break;
673+
}
674+
675+
if (outputTime > newestOutputFileTime) {
676+
newestOutputFileTime = outputTime;
677+
newestOutputFileName = output;
678+
}
679+
680+
// Keep track of when the most recent time a .d.ts file was changed.
681+
// In addition to file timestamps, we also keep track of when a .d.ts file
682+
// had its file touched but not had its contents changed - this allows us
683+
// to skip a downstream typecheck
684+
if (isDeclarationFile(output)) {
685+
const unchangedTime = context.unchangedOutputs.getValueOrUndefined(output);
686+
if (unchangedTime !== undefined) {
687+
newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
688+
}
689+
else {
690+
const outputModifiedTime = compilerHost.getModifiedTime!(output) || missingFileModifiedTime;
691+
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
692+
}
693+
}
694+
}
695+
696+
let pseudoUpToDate = false;
697+
let usesPrepend = false;
698+
let upstreamChangedProject: string | undefined;
699+
if (project.projectReferences) {
700+
for (const ref of project.projectReferences) {
701+
usesPrepend = usesPrepend || !!(ref.prepend);
702+
const resolvedRef = resolveProjectReferencePath(compilerHost, ref);
703+
const refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef));
704+
705+
// An upstream project is blocked
706+
if (refStatus.type === UpToDateStatusType.Unbuildable) {
707+
return {
708+
type: UpToDateStatusType.UpstreamBlocked,
709+
upstreamProjectName: ref.path
710+
};
711+
}
712+
713+
// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
714+
if (refStatus.type !== UpToDateStatusType.UpToDate) {
715+
return {
716+
type: UpToDateStatusType.UpstreamOutOfDate,
717+
upstreamProjectName: ref.path
718+
};
719+
}
720+
721+
// If the upstream project's newest file is older than our oldest output, we
722+
// can't be out of date because of it
723+
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
724+
continue;
725+
}
726+
727+
// If the upstream project has only change .d.ts files, and we've built
728+
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
729+
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
730+
pseudoUpToDate = true;
731+
upstreamChangedProject = ref.path;
732+
continue;
733+
}
734+
735+
// We have an output older than an upstream output - we are out of date
736+
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
737+
return {
738+
type: UpToDateStatusType.OutOfDateWithUpstream,
739+
outOfDateOutputFileName: oldestOutputFileName,
740+
newerProjectName: ref.path
741+
};
742+
}
743+
}
744+
745+
if (missingOutputFileName !== undefined) {
746+
return {
747+
type: UpToDateStatusType.OutputMissing,
748+
missingOutputFileName
749+
};
750+
}
751+
752+
if (isOutOfDateWithInputs) {
753+
return {
754+
type: UpToDateStatusType.OutOfDateWithSelf,
755+
outOfDateOutputFileName: oldestOutputFileName,
756+
newerInputFileName: newestInputFileName
757+
};
758+
}
759+
760+
if (usesPrepend && pseudoUpToDate) {
761+
return {
762+
type: UpToDateStatusType.OutOfDateWithUpstream,
763+
outOfDateOutputFileName: oldestOutputFileName,
764+
newerProjectName: upstreamChangedProject!
765+
};
766+
}
767+
768+
// Up to date
769+
return {
770+
type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
771+
newestDeclarationFileContentChangedTime,
772+
newestInputFileTime,
773+
newestOutputFileTime,
774+
newestInputFileName,
775+
newestOutputFileName,
776+
oldestOutputFileName
777+
};
615778
}
616779

617780
function invalidateProject(configFileName: string) {
@@ -1030,187 +1193,13 @@ namespace ts {
10301193
}
10311194
}
10321195

1033-
/**
1034-
* Gets the UpToDateStatus for a project
1035-
*/
1036-
export function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus {
1037-
if (project === undefined) {
1038-
return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" };
1039-
}
1040-
1041-
const prior = host.getLastStatus ? host.getLastStatus(project.options.configFilePath!) : undefined;
1042-
if (prior !== undefined) {
1043-
return prior;
1044-
}
1045-
1046-
const actual = getUpToDateStatusWorker(host, project);
1047-
if (host.setLastStatus) {
1048-
host.setLastStatus(project.options.configFilePath!, actual);
1049-
}
1050-
1051-
return actual;
1052-
}
1053-
1054-
function getUpToDateStatusWorker(host: UpToDateHost, project: ParsedCommandLine): UpToDateStatus {
1055-
let newestInputFileName: string = undefined!;
1056-
let newestInputFileTime = minimumDate;
1057-
// Get timestamps of input files
1058-
for (const inputFile of project.fileNames) {
1059-
if (!host.fileExists(inputFile)) {
1060-
return {
1061-
type: UpToDateStatusType.Unbuildable,
1062-
reason: `${inputFile} does not exist`
1063-
};
1064-
}
1065-
1066-
const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime;
1067-
if (inputTime > newestInputFileTime) {
1068-
newestInputFileName = inputFile;
1069-
newestInputFileTime = inputTime;
1070-
}
1071-
}
1072-
1073-
// Collect the expected outputs of this project
1074-
const outputs = getAllProjectOutputs(project);
1075-
1076-
if (outputs.length === 0) {
1077-
return {
1078-
type: UpToDateStatusType.ContainerOnly
1079-
};
1080-
}
1081-
1082-
// Now see if all outputs are newer than the newest input
1083-
let oldestOutputFileName = "(none)";
1084-
let oldestOutputFileTime = maximumDate;
1085-
let newestOutputFileName = "(none)";
1086-
let newestOutputFileTime = minimumDate;
1087-
let missingOutputFileName: string | undefined;
1088-
let newestDeclarationFileContentChangedTime = minimumDate;
1089-
let isOutOfDateWithInputs = false;
1090-
for (const output of outputs) {
1091-
// Output is missing; can stop checking
1092-
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1093-
if (!host.fileExists(output)) {
1094-
missingOutputFileName = output;
1095-
break;
1096-
}
1097-
1098-
const outputTime = host.getModifiedTime(output) || missingFileModifiedTime;
1099-
if (outputTime < oldestOutputFileTime) {
1100-
oldestOutputFileTime = outputTime;
1101-
oldestOutputFileName = output;
1102-
}
1103-
1104-
// If an output is older than the newest input, we can stop checking
1105-
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1106-
if (outputTime < newestInputFileTime) {
1107-
isOutOfDateWithInputs = true;
1108-
break;
1109-
}
1110-
1111-
if (outputTime > newestOutputFileTime) {
1112-
newestOutputFileTime = outputTime;
1113-
newestOutputFileName = output;
1114-
}
1115-
1116-
// Keep track of when the most recent time a .d.ts file was changed.
1117-
// In addition to file timestamps, we also keep track of when a .d.ts file
1118-
// had its file touched but not had its contents changed - this allows us
1119-
// to skip a downstream typecheck
1120-
if (isDeclarationFile(output)) {
1121-
const unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined;
1122-
if (unchangedTime !== undefined) {
1123-
newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime);
1124-
}
1125-
else {
1126-
const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime;
1127-
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
1128-
}
1129-
}
1130-
}
1131-
1132-
let pseudoUpToDate = false;
1133-
let usesPrepend = false;
1134-
let upstreamChangedProject: string | undefined;
1135-
if (project.projectReferences && host.parseConfigFile) {
1136-
for (const ref of project.projectReferences) {
1137-
usesPrepend = usesPrepend || !!(ref.prepend);
1138-
const resolvedRef = resolveProjectReferencePath(host, ref);
1139-
const refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef));
1140-
1141-
// An upstream project is blocked
1142-
if (refStatus.type === UpToDateStatusType.Unbuildable) {
1143-
return {
1144-
type: UpToDateStatusType.UpstreamBlocked,
1145-
upstreamProjectName: ref.path
1146-
};
1147-
}
1148-
1149-
// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
1150-
if (refStatus.type !== UpToDateStatusType.UpToDate) {
1151-
return {
1152-
type: UpToDateStatusType.UpstreamOutOfDate,
1153-
upstreamProjectName: ref.path
1154-
};
1155-
}
1156-
1157-
// If the upstream project's newest file is older than our oldest output, we
1158-
// can't be out of date because of it
1159-
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
1160-
continue;
1161-
}
1162-
1163-
// If the upstream project has only change .d.ts files, and we've built
1164-
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
1165-
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
1166-
pseudoUpToDate = true;
1167-
upstreamChangedProject = ref.path;
1168-
continue;
1169-
}
1170-
1171-
// We have an output older than an upstream output - we are out of date
1172-
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
1173-
return {
1174-
type: UpToDateStatusType.OutOfDateWithUpstream,
1175-
outOfDateOutputFileName: oldestOutputFileName,
1176-
newerProjectName: ref.path
1177-
};
1178-
}
1179-
}
1180-
1181-
if (missingOutputFileName !== undefined) {
1182-
return {
1183-
type: UpToDateStatusType.OutputMissing,
1184-
missingOutputFileName
1185-
};
1186-
}
1187-
1188-
if (isOutOfDateWithInputs) {
1189-
return {
1190-
type: UpToDateStatusType.OutOfDateWithSelf,
1191-
outOfDateOutputFileName: oldestOutputFileName,
1192-
newerInputFileName: newestInputFileName
1193-
};
1194-
}
1195-
1196-
if (usesPrepend && pseudoUpToDate) {
1197-
return {
1198-
type: UpToDateStatusType.OutOfDateWithUpstream,
1199-
outOfDateOutputFileName: oldestOutputFileName,
1200-
newerProjectName: upstreamChangedProject!
1201-
};
1202-
}
1203-
1204-
// Up to date
1205-
return {
1206-
type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate,
1207-
newestDeclarationFileContentChangedTime,
1208-
newestInputFileTime,
1209-
newestOutputFileTime,
1210-
newestInputFileName,
1211-
newestOutputFileName,
1212-
oldestOutputFileName
1213-
};
1196+
export interface UpToDateHost {
1197+
fileExists(fileName: string): boolean;
1198+
getModifiedTime(fileName: string): Date | undefined;
1199+
getUnchangedTime?(fileName: string): Date | undefined;
1200+
getLastStatus?(fileName: string): UpToDateStatus | undefined;
1201+
setLastStatus?(fileName: string, status: UpToDateStatus): void;
1202+
parseConfigFile?(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined;
12141203
}
12151204

12161205
export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string> {

0 commit comments

Comments
 (0)