Skip to content

Commit

Permalink
Do project reference errors before doing input/output file checks
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed Apr 19, 2022
1 parent 7817fbf commit cb7aca3
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 135 deletions.
170 changes: 80 additions & 90 deletions src/compiler/tsbuildPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1346,14 +1346,52 @@ namespace ts {
}

function getUpToDateStatusWorker(state: SolutionBuilderState, project: ParsedCommandLine, resolvedPath: ResolvedConfigFilePath): UpToDateStatus {
// Container if no files are specified in the project
if (!project.fileNames.length && !canJsonReportNoInputFiles(project.raw)) {
// Container if no files are specified in the project
if (!project.fileNames.length && !canJsonReportNoInputFiles(project.raw)) {
return {
type: UpToDateStatusType.ContainerOnly
};
}

// Fast check to see if reference projects are buildable
let referenceStatuses;
const force = !!state.options.force;
if (project.projectReferences) {
state.projectStatus.set(resolvedPath, { type: UpToDateStatusType.ComputingUpstream });
for (const ref of project.projectReferences) {
const resolvedRef = resolveProjectReferencePath(ref);
const resolvedRefPath = toResolvedConfigFilePath(state, resolvedRef);
const refStatus = getUpToDateStatus(state, parseConfigFile(state, resolvedRef, resolvedRefPath), resolvedRefPath);

// Its a circular reference ignore the status of this project
if (refStatus.type === UpToDateStatusType.ComputingUpstream ||
refStatus.type === UpToDateStatusType.ContainerOnly) { // Container only ignore this project
continue;
}

// An upstream project is blocked
if (refStatus.type === UpToDateStatusType.Unbuildable ||
refStatus.type === UpToDateStatusType.UpstreamBlocked) {
return {
type: UpToDateStatusType.UpstreamBlocked,
upstreamProjectName: ref.path,
upstreamProjectBlocked: refStatus.type === UpToDateStatusType.UpstreamBlocked
};
}

// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
if (refStatus.type !== UpToDateStatusType.UpToDate) {
return {
type: UpToDateStatusType.UpstreamOutOfDate,
upstreamProjectName: ref.path
};
}

if (!force) (referenceStatuses ||= []).push({ ref, refStatus });
}
}

// Check output files
let newestInputFileName: string = undefined!;
let newestInputFileTime = minimumDate;
const { host } = state;
Expand Down Expand Up @@ -1381,17 +1419,16 @@ namespace ts {
// Now see if all outputs are newer than the newest input
let oldestOutputFileName = "(none)";
let oldestOutputFileTime = maximumDate;
let missingOutputFileName: string | undefined;
let newestDeclarationFileContentChangedTime = minimumDate;
let isOutOfDateWithInputs = false;
if (!force) {
for (const output of outputs) {
// Output is missing; can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
const outputTime = getModifiedTime(host, output);
if (outputTime === missingFileModifiedTime) {
missingOutputFileName = output;
break;
return {
type: UpToDateStatusType.OutputMissing,
missingOutputFileName: output
};
}

if (outputTime < oldestOutputFileTime) {
Expand All @@ -1400,10 +1437,12 @@ namespace ts {
}

// If an output is older than the newest input, we can stop checking
// Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
if (outputTime < newestInputFileTime) {
isOutOfDateWithInputs = true;
break;
return {
type: UpToDateStatusType.OutOfDateWithSelf,
outOfDateOutputFileName: oldestOutputFileName,
newerInputFileName: newestInputFileName
};
}

// Keep track of when the most recent time a .d.ts file was changed.
Expand All @@ -1419,96 +1458,47 @@ namespace ts {
let pseudoUpToDate = false;
let usesPrepend = false;
let upstreamChangedProject: string | undefined;
if (project.projectReferences) {
state.projectStatus.set(resolvedPath, { type: UpToDateStatusType.ComputingUpstream });
for (const ref of project.projectReferences) {
if (referenceStatuses) {
for (const { ref, refStatus } of referenceStatuses) {
usesPrepend = usesPrepend || !!(ref.prepend);
const resolvedRef = resolveProjectReferencePath(ref);
const resolvedRefPath = toResolvedConfigFilePath(state, resolvedRef);
const refStatus = getUpToDateStatus(state, parseConfigFile(state, resolvedRef, resolvedRefPath), resolvedRefPath);

// Its a circular reference ignore the status of this project
if (refStatus.type === UpToDateStatusType.ComputingUpstream ||
refStatus.type === UpToDateStatusType.ContainerOnly) { // Container only ignore this project
// If the upstream project's newest file is older than our oldest output, we
// can't be out of date because of it
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
continue;
}

// An upstream project is blocked
if (refStatus.type === UpToDateStatusType.Unbuildable ||
refStatus.type === UpToDateStatusType.UpstreamBlocked) {
return {
type: UpToDateStatusType.UpstreamBlocked,
upstreamProjectName: ref.path,
upstreamProjectBlocked: refStatus.type === UpToDateStatusType.UpstreamBlocked
};
}

// If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
if (refStatus.type !== UpToDateStatusType.UpToDate) {
return {
type: UpToDateStatusType.UpstreamOutOfDate,
upstreamProjectName: ref.path
};
// If the upstream project has only change .d.ts files, and we've built
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
pseudoUpToDate = true;
upstreamChangedProject = ref.path;
continue;
}

// Check oldest output file name only if there is no missing output file name
// (a check we will have skipped if this is a forced build)
if (!force && !missingOutputFileName) {
// If the upstream project's newest file is older than our oldest output, we
// can't be out of date because of it
if (refStatus.newestInputFileTime && refStatus.newestInputFileTime <= oldestOutputFileTime) {
continue;
}

// If the upstream project has only change .d.ts files, and we've built
// *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
if (refStatus.newestDeclarationFileContentChangedTime && refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) {
pseudoUpToDate = true;
upstreamChangedProject = ref.path;
continue;
}

// We have an output older than an upstream output - we are out of date
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: ref.path
};
}
// We have an output older than an upstream output - we are out of date
Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here");
return {
type: UpToDateStatusType.OutOfDateWithUpstream,
outOfDateOutputFileName: oldestOutputFileName,
newerProjectName: ref.path
};
}
}

if (missingOutputFileName !== undefined) {
return {
type: UpToDateStatusType.OutputMissing,
missingOutputFileName
};
}
// Check tsconfig time
const configStatus = checkConfigFileUpToDateStatus(state, project.options.configFilePath!, oldestOutputFileTime, oldestOutputFileName);
if (configStatus) return configStatus;

if (isOutOfDateWithInputs) {
return {
type: UpToDateStatusType.OutOfDateWithSelf,
outOfDateOutputFileName: oldestOutputFileName,
newerInputFileName: newestInputFileName
};
}
else {
// Check tsconfig time
const configStatus = checkConfigFileUpToDateStatus(state, project.options.configFilePath!, oldestOutputFileTime, oldestOutputFileName);
if (configStatus) return configStatus;

// Check extended config time
const extendedConfigStatus = forEach(project.options.configFile!.extendedSourceFiles || emptyArray, configFile => checkConfigFileUpToDateStatus(state, configFile, oldestOutputFileTime, oldestOutputFileName));
if (extendedConfigStatus) return extendedConfigStatus;

// Check package file time
const dependentPackageFileStatus = forEach(
state.lastCachedPackageJsonLookups.get(resolvedPath) || emptyArray,
([path]) => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName)
);
if (dependentPackageFileStatus) return dependentPackageFileStatus;
}
// Check extended config time
const extendedConfigStatus = forEach(project.options.configFile!.extendedSourceFiles || emptyArray, configFile => checkConfigFileUpToDateStatus(state, configFile, oldestOutputFileTime, oldestOutputFileName));
if (extendedConfigStatus) return extendedConfigStatus;

// Check package file time
const dependentPackageFileStatus = forEach(
state.lastCachedPackageJsonLookups.get(resolvedPath) || emptyArray,
([path]) => checkConfigFileUpToDateStatus(state, path, oldestOutputFileTime, oldestOutputFileName)
);
if (dependentPackageFileStatus) return dependentPackageFileStatus;

if (!force && !state.buildInfoChecked.has(resolvedPath)) {
state.buildInfoChecked.set(resolvedPath, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,7 @@ exitCode:: ExitStatus.DiagnosticsPresent_OutputsSkipped

getModifiedTime:: {
"/src/core/utilities.ts": 1,
"/src/lib/core/utilities.js": 1,
"/src/animals/animal.ts": 1,
"/src/animals/dog.ts": 1,
"/src/animals/index.ts": 1,
"/src/lib/animals/animal.js": 1,
"/src/zoo/zoo.ts": 1,
"/src/lib/zoo/zoo.js": 1
"/src/lib/core/utilities.js": 1
}

setModifiedTime:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ getModifiedTime:: {
"/src/core/some_decl.d.ts": 1,
"/src/core/anotherModule.js": 1,
"/src/logic/index.ts": 1,
"/src/logic/index.js": 1,
"/src/tests/index.ts": 1,
"/src/tests/index.js": 1
"/src/logic/index.js": 1
}

setModifiedTime:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,7 @@ getModifiedTime:: {
"/src/core/anotherModule.ts": 1,
"/src/core/index.ts": 1,
"/src/core/some_decl.d.ts": 1,
"/src/core/anotherModule.js": 1,
"/src/logic/index.ts": 1,
"/src/logic/index.js": 1,
"/src/tests/index.ts": 1,
"/src/tests/index.js": 1
"/src/core/anotherModule.js": 1
}

setModifiedTime:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ getModifiedTime:: {
"/src/a.ts": 1,
"/src/a.js": 1,
"/src/b.ts": 1,
"/src/b.js": 1,
"/src/c.ts": 1,
"/src/c.js": 1
"/src/b.js": 1
}

setModifiedTime:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,13 +449,7 @@ directoryExists:: {

getModifiedTimes:: {
"/user/username/projects/demo/core/utilities.ts": 1,
"/user/username/projects/demo/lib/core/utilities.js": 1,
"/user/username/projects/demo/animals/animal.ts": 1,
"/user/username/projects/demo/animals/dog.ts": 1,
"/user/username/projects/demo/animals/index.ts": 1,
"/user/username/projects/demo/lib/animals/animal.js": 1,
"/user/username/projects/demo/zoo/zoo.ts": 1,
"/user/username/projects/demo/lib/zoo/zoo.js": 1
"/user/username/projects/demo/lib/core/utilities.js": 1
}

setModifiedTimes:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ Output::
>> Screen clear
[12:01:31 AM] File change detected. Starting incremental compilation...

[[90m12:01:32 AM[0m] Project 'sample1/logic/tsconfig.json' is out of date because oldest output 'sample1/logic/index.js' is older than newest input 'sample1/core'
[[90m12:01:32 AM[0m] Project 'sample1/logic/tsconfig.json' is out of date because oldest output 'sample1/logic/index.js' is older than newest input 'sample1/logic/index.ts'

[12:01:33 AM] Building project '/user/username/projects/sample1/logic/tsconfig.json'...

Expand Down Expand Up @@ -746,7 +746,7 @@ Output::
>> Screen clear
[12:01:56 AM] File change detected. Starting incremental compilation...

[[90m12:01:57 AM[0m] Project 'sample1/logic/tsconfig.json' is out of date because oldest output 'sample1/logic/index.js' is older than newest input 'sample1/core'
[[90m12:01:57 AM[0m] Project 'sample1/logic/tsconfig.json' is out of date because oldest output 'sample1/logic/index.js' is older than newest input 'sample1/logic/index.ts'

[12:01:58 AM] Building project '/user/username/projects/sample1/logic/tsconfig.json'...

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,7 @@ directoryExists:: {
getModifiedTimes:: {
"/user/username/projects/sample1/core/anothermodule.ts": 1,
"/user/username/projects/sample1/core/index.ts": 1,
"/user/username/projects/sample1/core/anothermodule.js": 1,
"/user/username/projects/sample1/tests/index.ts": 1,
"/user/username/projects/sample1/tests/index.js": 1
"/user/username/projects/sample1/core/anothermodule.js": 1
}

setModifiedTimes:: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,6 @@ directoryExists:: {
}

getModifiedTimes:: {
"/user/username/projects/sample1/core/anothermodule.ts": 1,
"/user/username/projects/sample1/core/index.ts": 1,
"/user/username/projects/sample1/core/anothermodule.js": 1,
"/user/username/projects/sample1/tests/index.ts": 1,
"/user/username/projects/sample1/tests/index.js": 1,
"/user/username/projects/sample1/logic/index.ts": 1,
"/user/username/projects/sample1/logic/index.js": 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,6 @@ directoryExists:: {
}

getModifiedTimes:: {
"/user/username/projects/sample1/core/anothermodule.ts": 1,
"/user/username/projects/sample1/core/index.ts": 1,
"/user/username/projects/sample1/core/anothermodule.js": 1,
"/user/username/projects/sample1/tests/index.ts": 1,
"/user/username/projects/sample1/tests/index.js": 1,
"/user/username/projects/sample1/logic/index.ts": 1,
"/user/username/projects/sample1/logic/index.js": 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,6 @@ directoryExists:: {
}

getModifiedTimes:: {
"/user/username/projects/sample1/core/anothermodule.ts": 1,
"/user/username/projects/sample1/core/index.ts": 1,
"/user/username/projects/sample1/core/anothermodule.js": 1,
"/user/username/projects/sample1/tests/index.ts": 1,
"/user/username/projects/sample1/tests/index.js": 1,
"/user/username/projects/sample1/logic/index.ts": 1,
"/user/username/projects/sample1/logic/index.js": 1
}
Expand Down

0 comments on commit cb7aca3

Please sign in to comment.