Skip to content

Commit

Permalink
Store output time stamps for non incremental builds
Browse files Browse the repository at this point in the history
  • Loading branch information
sheetalkamat committed Apr 19, 2022
1 parent 128008a commit 4fb6773
Show file tree
Hide file tree
Showing 19 changed files with 300 additions and 321 deletions.
51 changes: 40 additions & 11 deletions src/compiler/tsbuildPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ namespace ts {
readonly projectStatus: ESMap<ResolvedConfigFilePath, UpToDateStatus>;
readonly extendedConfigCache: ESMap<string, ExtendedConfigCacheEntry>;
readonly buildInfoCache: ESMap<ResolvedConfigFilePath, BuildInfoCacheEntry>;
readonly outputTimeStamps: ESMap<ResolvedConfigFilePath, ESMap<Path, Date>>;

readonly builderPrograms: ESMap<ResolvedConfigFilePath, T>;
readonly diagnostics: ESMap<ResolvedConfigFilePath, readonly Diagnostic[]>;
Expand Down Expand Up @@ -330,6 +331,7 @@ namespace ts {
projectStatus: new Map(),
extendedConfigCache: new Map(),
buildInfoCache: new Map(),
outputTimeStamps: new Map(),

builderPrograms: new Map(),
diagnostics: new Map(),
Expand Down Expand Up @@ -493,6 +495,7 @@ namespace ts {
mutateMapSkippingNewValues(state.projectPendingBuild, currentProjects, noopOnDelete);
mutateMapSkippingNewValues(state.projectErrorsReported, currentProjects, noopOnDelete);
mutateMapSkippingNewValues(state.buildInfoCache, currentProjects, noopOnDelete);
mutateMapSkippingNewValues(state.outputTimeStamps, currentProjects, noopOnDelete);

// Remove watches for the program no longer in the solution
if (state.watch) {
Expand Down Expand Up @@ -983,15 +986,23 @@ namespace ts {
const existingBuildInfo = state.buildInfoCache.get(projectPath)?.buildInfo || undefined;
const emitterDiagnostics = createDiagnosticCollection();
const emittedOutputs = new Map<Path, string>();
const options = program.getCompilerOptions();
const isIncremental = isIncrementalCompilation(options);
let outputTimeStampMap: ESMap<Path, Date> | undefined;
let now: Date | undefined;
outputFiles.forEach(({ name, text, writeByteOrderMark, buildInfo }) => {
const path = toPath(state, name);
emittedOutputs.set(toPath(state, name), name);
if (buildInfo) {
setBuildInfo(state, buildInfo, projectPath, program!.getCompilerOptions());
setBuildInfo(state, buildInfo, projectPath, options);
if (buildInfo.program?.dtsChangeTime !== existingBuildInfo?.program?.dtsChangeTime) {
resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged;
}
}
writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
if (!isIncremental) {
(outputTimeStampMap ||= getOutputTimeStampMap(state, projectPath)).set(path, now ||= getCurrentTime(state.host));
}
});

finishEmit(
Expand Down Expand Up @@ -1050,7 +1061,7 @@ namespace ts {
}

// Update time stamps for rest of the outputs
updateOutputTimestampsWorker(state, config, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
updateOutputTimestampsWorker(state, config, projectPath, Diagnostics.Updating_unchanged_output_timestamps_of_project_0, emittedOutputs);
state.diagnostics.delete(projectPath);
state.projectStatus.set(projectPath, {
type: UpToDateStatusType.UpToDate,
Expand Down Expand Up @@ -1402,6 +1413,12 @@ namespace ts {
};
}

function getOutputTimeStampMap(state: SolutionBuilderState, resolvedConfigFilePath: ResolvedConfigFilePath) {
let result = state.outputTimeStamps.get(resolvedConfigFilePath);
if (!result) state.outputTimeStamps.set(resolvedConfigFilePath, result = new Map());
return result;
}

function setBuildInfo(state: SolutionBuilderState, buildInfo: BuildInfo, resolvedConfigPath: ResolvedConfigFilePath, options: CompilerOptions) {
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options)!;
const existing = getBuildInfoCacheEntry(state, buildInfoPath, resolvedConfigPath);
Expand Down Expand Up @@ -1573,9 +1590,12 @@ namespace ts {
if (!buildInfoPath) {
// Collect the expected outputs of this project
const outputs = getAllProjectOutputs(project, !host.useCaseSensitiveFileNames());
const outputTimeStampMap = getOutputTimeStampMap(state, resolvedPath);
for (const output of outputs) {
const path = toPath(state, output);
// Output is missing; can stop checking
const outputTime = ts.getModifiedTime(state.host, output);
let outputTime = outputTimeStampMap.get(path);
if (!outputTime) outputTimeStampMap.set(path, outputTime = ts.getModifiedTime(state.host, output));
if (outputTime === missingFileModifiedTime) {
return {
type: UpToDateStatusType.OutputMissing,
Expand Down Expand Up @@ -1711,37 +1731,46 @@ namespace ts {
function updateOutputTimestampsWorker(
state: SolutionBuilderState,
proj: ParsedCommandLine,
projectPath: ResolvedConfigFilePath,
verboseMessage: DiagnosticMessage,
skipOutputs?: ESMap<Path, string>
) {
if (proj.options.noEmit) return;
let now: Date | undefined;
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(proj.options);
if (buildInfoPath) {
if (!skipOutputs?.has(toPath(state, buildInfoPath))) {
if (!!state.options.verbose) reportStatus(state, verboseMessage, proj.options.configFilePath!);
state.host.setModifiedTime(buildInfoPath, getCurrentTime(state.host));
state.host.setModifiedTime(buildInfoPath, now = getCurrentTime(state.host));
getBuildInfoCacheEntry(state, buildInfoPath, projectPath)!.modifiedTime = now;
}
state.outputTimeStamps.delete(projectPath);
return;
}

const { host } = state;
const outputs = getAllProjectOutputs(proj, !host.useCaseSensitiveFileNames());
const outputTimeStampMap = getOutputTimeStampMap(state, projectPath);
const modifiedOutputs = new Set<Path>();
if (!skipOutputs || outputs.length !== skipOutputs.size) {
let reportVerbose = !!state.options.verbose;
let now: Date | undefined;
for (const file of outputs) {
if (skipOutputs && skipOutputs.has(toPath(state, file))) {
continue;
}

const path = toPath(state, file);
if (skipOutputs?.has(path)) continue;
if (reportVerbose) {
reportVerbose = false;
reportStatus(state, verboseMessage, proj.options.configFilePath!);
}

host.setModifiedTime(file, now ||= getCurrentTime(state.host));
outputTimeStampMap.set(path, now);
modifiedOutputs.add(path);
}
}

// Clear out timestamps not in output list any more
outputTimeStampMap.forEach((_value, key) => {
if (!skipOutputs?.has(key) && !modifiedOutputs.has(key)) outputTimeStampMap.delete(key);
});
}

function getDtsChangeTime(state: SolutionBuilderState, options: CompilerOptions, resolvedConfigPath: ResolvedConfigFilePath) {
Expand All @@ -1755,7 +1784,7 @@ namespace ts {
if (state.options.dry) {
return reportStatus(state, Diagnostics.A_non_dry_build_would_update_timestamps_for_output_of_project_0, proj.options.configFilePath!);
}
updateOutputTimestampsWorker(state, proj, Diagnostics.Updating_output_timestamps_of_project_0);
updateOutputTimestampsWorker(state, proj, resolvedPath, Diagnostics.Updating_output_timestamps_of_project_0);
state.projectStatus.set(resolvedPath, {
type: UpToDateStatusType.UpToDate,
newestDeclarationFileContentChangedTime: getDtsChangeTime(state, proj.options, resolvedPath),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -821,24 +821,24 @@ console.log(s);console.log(s);

Output::
/lib/tsc --b /src/third --verbose --incremental
[[90m12:01:04 AM[0m] Projects in this build:
[[90m12:01:05 AM[0m] Projects in this build:
* src/first/tsconfig.json
* src/second/tsconfig.json
* src/third/tsconfig.json

[[90m12:01:05 AM[0m] Project 'src/first/tsconfig.json' is out of date because oldest output 'src/first/bin/first-output.tsbuildinfo' is older than newest input 'src/first/first_PART1.ts'
[[90m12:01:06 AM[0m] Project 'src/first/tsconfig.json' is out of date because oldest output 'src/first/bin/first-output.tsbuildinfo' is older than newest input 'src/first/first_PART1.ts'

[[90m12:01:06 AM[0m] Building project '/src/first/tsconfig.json'...
[[90m12:01:07 AM[0m] Building project '/src/first/tsconfig.json'...

[[90m12:01:15 AM[0m] Project 'src/second/tsconfig.json' is up to date because newest input 'src/second/second_part1.ts' is older than oldest output 'src/2/second-output.tsbuildinfo'
[[90m12:01:16 AM[0m] Project 'src/second/tsconfig.json' is up to date because newest input 'src/second/second_part1.ts' is older than oldest output 'src/2/second-output.tsbuildinfo'

[[90m12:01:16 AM[0m] Project 'src/third/tsconfig.json' is out of date because output of its dependency 'src/first' has changed
[[90m12:01:17 AM[0m] Project 'src/third/tsconfig.json' is out of date because output of its dependency 'src/first' has changed

[[90m12:01:17 AM[0m] Updating output of project '/src/third/tsconfig.json'...
[[90m12:01:18 AM[0m] Updating output of project '/src/third/tsconfig.json'...

[[90m12:01:18 AM[0m] Cannot update output of project '/src/third/tsconfig.json' because there was error reading file 'src/third/thirdjs/output/third-output.js'
[[90m12:01:19 AM[0m] Cannot update output of project '/src/third/tsconfig.json' because there was error reading file 'src/third/thirdjs/output/third-output.js'

[[90m12:01:19 AM[0m] Building project '/src/third/tsconfig.json'...
[[90m12:01:20 AM[0m] Building project '/src/third/tsconfig.json'...

exitCode:: ExitStatus.Success

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1774,20 +1774,20 @@ console.log(s);

Output::
/lib/tsc --b /src/third --verbose
[[90m12:00:47 AM[0m] Projects in this build:
[[90m12:00:48 AM[0m] Projects in this build:
* src/first/tsconfig.json
* src/second/tsconfig.json
* src/third/tsconfig.json

[[90m12:00:48 AM[0m] Project 'src/first/tsconfig.json' is out of date because oldest output 'src/first/bin/first-output.tsbuildinfo' is older than newest input 'src/first/first_PART1.ts'
[[90m12:00:49 AM[0m] Project 'src/first/tsconfig.json' is out of date because oldest output 'src/first/bin/first-output.tsbuildinfo' is older than newest input 'src/first/first_PART1.ts'

[[90m12:00:49 AM[0m] Building project '/src/first/tsconfig.json'...
[[90m12:00:50 AM[0m] Building project '/src/first/tsconfig.json'...

[[90m12:00:58 AM[0m] Project 'src/second/tsconfig.json' is up to date because newest input 'src/second/second_part1.ts' is older than oldest output 'src/2/second-output.tsbuildinfo'
[[90m12:00:59 AM[0m] Project 'src/second/tsconfig.json' is up to date because newest input 'src/second/second_part1.ts' is older than oldest output 'src/2/second-output.tsbuildinfo'

[[90m12:00:59 AM[0m] Project 'src/third/tsconfig.json' is out of date because output of its dependency 'src/first' has changed
[[90m12:01:00 AM[0m] Project 'src/third/tsconfig.json' is out of date because output of its dependency 'src/first' has changed

[[90m12:01:00 AM[0m] Building project '/src/third/tsconfig.json'...
[[90m12:01:01 AM[0m] Building project '/src/third/tsconfig.json'...

exitCode:: ExitStatus.Success

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ Input::

Output::
/lib/tsc --b /src/tsconfig.json -v
[[90m12:00:14 AM[0m] Projects in this build:
[[90m12:00:15 AM[0m] Projects in this build:
* src/tsconfig.json

[[90m12:00:15 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'
[[90m12:00:16 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'

exitCode:: ExitStatus.Success

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ Input::

Output::
/lib/tsc --b /src/tsconfig.json -v
[[90m12:00:14 AM[0m] Projects in this build:
[[90m12:00:15 AM[0m] Projects in this build:
* src/tsconfig.json

[[90m12:00:15 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'
[[90m12:00:16 AM[0m] Project 'src/tsconfig.json' is up to date because newest input 'src/src/index.ts' is older than oldest output 'src/dist/index.js'

exitCode:: ExitStatus.Success

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ File '/user/username/projects/myproject/packages/pkg2/build/const.ts' does not e
File '/user/username/projects/myproject/packages/pkg2/build/const.tsx' does not exist.
File '/user/username/projects/myproject/packages/pkg2/build/const.d.ts' exist - use it as a name resolution result.
======== Module name './const.js' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/build/const.d.ts'. ========
[[90m12:01:15 AM[0m] Found 0 errors. Watching for file changes.
[[90m12:01:16 AM[0m] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -349,11 +349,11 @@ setModifiedTimes:: {}

Output::
>> Screen clear
[[90m12:01:19 AM[0m] File change detected. Starting incremental compilation...
[[90m12:01:20 AM[0m] File change detected. Starting incremental compilation...

[[90m12:01:20 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because oldest output 'packages/pkg1/build/index.js' is older than newest input 'packages/pkg2/package.json'
[[90m12:01:21 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because oldest output 'packages/pkg1/build/index.js' is older than newest input 'packages/pkg2/package.json'

[[90m12:01:21 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...
[[90m12:01:22 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...

======== Resolving module 'pkg2' from '/user/username/projects/myproject/packages/pkg1/index.ts'. ========
Module resolution kind is not specified, using 'NodeJs'.
Expand Down Expand Up @@ -385,7 +385,7 @@ Resolving real path for '/user/username/projects/myproject/node_modules/pkg2/bui
1 import type { TheNum } from 'pkg2'
   ~~~~~~

[[90m12:01:22 AM[0m] Found 1 error. Watching for file changes.
[[90m12:01:23 AM[0m] Found 1 error. Watching for file changes.



Expand Down Expand Up @@ -463,7 +463,6 @@ directoryExists:: {
}

getModifiedTimes:: {
"/user/username/projects/myproject/packages/pkg1/build/index.js": 1,
"/user/username/projects/myproject/packages/pkg1/tsconfig.json": 1
}

Expand All @@ -486,11 +485,11 @@ setModifiedTimes:: {}

Output::
>> Screen clear
[[90m12:01:26 AM[0m] File change detected. Starting incremental compilation...
[[90m12:01:27 AM[0m] File change detected. Starting incremental compilation...

[[90m12:01:27 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because oldest output 'packages/pkg1/build/index.js' is older than newest input 'packages/pkg2/package.json'
[[90m12:01:28 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because oldest output 'packages/pkg1/build/index.js' is older than newest input 'packages/pkg2/package.json'

[[90m12:01:28 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...
[[90m12:01:29 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...

======== Resolving module 'pkg2' from '/user/username/projects/myproject/packages/pkg1/index.ts'. ========
Module resolution kind is not specified, using 'NodeJs'.
Expand Down Expand Up @@ -529,7 +528,7 @@ File '/user/username/projects/myproject/packages/pkg2/build/const.ts' does not e
File '/user/username/projects/myproject/packages/pkg2/build/const.tsx' does not exist.
File '/user/username/projects/myproject/packages/pkg2/build/const.d.ts' exist - use it as a name resolution result.
======== Module name './const.js' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/build/const.d.ts'. ========
[[90m12:01:32 AM[0m] Found 0 errors. Watching for file changes.
[[90m12:01:34 AM[0m] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -617,8 +616,6 @@ directoryExists:: {
"/node_modules/@types": 1
}

getModifiedTimes:: {
"/user/username/projects/myproject/packages/pkg1/build/index.js": 1
}
getModifiedTimes:: {}

setModifiedTimes:: {}
Loading

0 comments on commit 4fb6773

Please sign in to comment.