Skip to content

Commit 5270b7e

Browse files
committed
Make invalidated projects as api so we can expose it later
1 parent 6227fab commit 5270b7e

File tree

1 file changed

+132
-78
lines changed

1 file changed

+132
-78
lines changed

src/compiler/tsbuild.ts

Lines changed: 132 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -283,30 +283,6 @@ namespace ts {
283283
/*@internal*/ buildNextInvalidatedProject(): void;
284284
}
285285

286-
const enum InvalidatedProjectKind {
287-
BuildProject,
288-
UpdateBundle,
289-
UpdateOutputFileStamps
290-
}
291-
292-
interface UpdateOutputFileStampsProject {
293-
readonly kind: InvalidatedProjectKind.UpdateOutputFileStamps;
294-
readonly project: ResolvedConfigFileName;
295-
readonly projectPath: ResolvedConfigFilePath;
296-
readonly config: ParsedCommandLine;
297-
}
298-
299-
interface BuildOrUpdateBundleProject {
300-
readonly kind: InvalidatedProjectKind.BuildProject | InvalidatedProjectKind.UpdateBundle;
301-
readonly project: ResolvedConfigFileName;
302-
readonly projectPath: ResolvedConfigFilePath;
303-
readonly projectIndex: number;
304-
readonly config: ParsedCommandLine;
305-
readonly buildOrder: readonly ResolvedConfigFileName[];
306-
}
307-
308-
type InvalidatedProject = UpdateOutputFileStampsProject | BuildOrUpdateBundleProject;
309-
310286
/**
311287
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
312288
*/
@@ -678,6 +654,121 @@ namespace ts {
678654
}
679655
}
680656

657+
const enum InvalidatedProjectKind {
658+
Build,
659+
UpdateBundle,
660+
UpdateOutputFileStamps
661+
}
662+
663+
interface InvalidatedProjectBase {
664+
readonly kind: InvalidatedProjectKind;
665+
readonly project: ResolvedConfigFileName;
666+
readonly projectPath: ResolvedConfigFilePath;
667+
/**
668+
* To dispose this project and ensure that all the necessary actions are taken and state is updated accordingly
669+
*/
670+
done(cancellationToken?: CancellationToken): void;
671+
}
672+
673+
interface UpdateOutputFileStampsProject extends InvalidatedProjectBase {
674+
readonly kind: InvalidatedProjectKind.UpdateOutputFileStamps;
675+
updateOutputFileStatmps(): void;
676+
}
677+
678+
interface BuildInvalidedProject extends InvalidatedProjectBase {
679+
readonly kind: InvalidatedProjectKind.Build;
680+
build(cancellationToken?: CancellationToken): BuildResultFlags;
681+
}
682+
683+
interface UpdateBundleProject extends InvalidatedProjectBase {
684+
readonly kind: InvalidatedProjectKind.UpdateBundle;
685+
updateBundle(cancellationToken?: CancellationToken): BuildResultFlags;
686+
}
687+
688+
type InvalidatedProject = UpdateOutputFileStampsProject | BuildInvalidedProject | UpdateBundleProject;
689+
690+
function createUpdateOutputFileStampsProject(state: SolutionBuilderState, project: ResolvedConfigFileName, projectPath: ResolvedConfigFilePath, config: ParsedCommandLine): UpdateOutputFileStampsProject {
691+
let updateOutputFileStampsPending = true;
692+
return {
693+
kind: InvalidatedProjectKind.UpdateOutputFileStamps,
694+
project,
695+
projectPath,
696+
updateOutputFileStatmps: () => {
697+
updateOutputTimestamps(state, config, projectPath);
698+
updateOutputFileStampsPending = false;
699+
},
700+
done: () => {
701+
if (updateOutputFileStampsPending) {
702+
updateOutputTimestamps(state, config, projectPath);
703+
}
704+
state.projectPendingBuild.delete(projectPath);
705+
}
706+
};
707+
}
708+
709+
function createBuildInvalidedProject(
710+
state: SolutionBuilderState,
711+
project: ResolvedConfigFileName,
712+
projectPath: ResolvedConfigFilePath,
713+
projectIndex: number,
714+
config: ParsedCommandLine,
715+
buildOrder: readonly ResolvedConfigFileName[]
716+
): BuildInvalidedProject {
717+
let buildPending = true;
718+
return {
719+
kind: InvalidatedProjectKind.Build,
720+
project,
721+
projectPath,
722+
build,
723+
done: cancellationToken => {
724+
if (buildPending) build(cancellationToken);
725+
state.projectPendingBuild.delete(projectPath);
726+
}
727+
};
728+
729+
function build(cancellationToken?: CancellationToken) {
730+
const buildResult = buildSingleProject(state, project, projectPath, config, cancellationToken);
731+
queueReferencingProjects(state, project, projectPath, projectIndex, config, buildOrder, buildResult);
732+
buildPending = false;
733+
return buildResult;
734+
}
735+
}
736+
737+
function createUpdateBundleProject(
738+
state: SolutionBuilderState,
739+
project: ResolvedConfigFileName,
740+
projectPath: ResolvedConfigFilePath,
741+
projectIndex: number,
742+
config: ParsedCommandLine,
743+
buildOrder: readonly ResolvedConfigFileName[]
744+
): UpdateBundleProject {
745+
let updatePending = true;
746+
return {
747+
kind: InvalidatedProjectKind.UpdateBundle,
748+
project,
749+
projectPath,
750+
updateBundle: update,
751+
done: cancellationToken => {
752+
if (updatePending) update(cancellationToken);
753+
state.projectPendingBuild.delete(projectPath);
754+
}
755+
};
756+
757+
function update(cancellationToken?: CancellationToken) {
758+
const buildResult = updateBundle(state, project, projectPath, config, cancellationToken);
759+
queueReferencingProjects(state, project, projectPath, projectIndex, config, buildOrder, buildResult);
760+
updatePending = false;
761+
return buildResult;
762+
}
763+
}
764+
765+
function needsBuild({ options }: SolutionBuilderState, status: UpToDateStatus, config: ParsedCommandLine) {
766+
if (status.type !== UpToDateStatusType.OutOfDateWithPrepend || options.force) return true;
767+
return config.fileNames.length === 0 ||
768+
!!config.errors.length ||
769+
!isIncrementalCompilation(config.options);
770+
}
771+
681772
function getNextInvalidatedProject(state: SolutionBuilderState, buildOrder: readonly ResolvedConfigFileName[]): InvalidatedProject | undefined {
682773
if (!state.projectPendingBuild.size) return undefined;
683774

@@ -724,14 +815,12 @@ namespace ts {
724815

725816
if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes) {
726817
reportAndStoreErrors(state, projectPath, config.errors);
727-
return {
728-
kind: InvalidatedProjectKind.UpdateOutputFileStamps,
818+
return createUpdateOutputFileStampsProject(
819+
state,
729820
project,
730821
projectPath,
731822
config
732-
};
733-
734-
continue;
823+
);
735824
}
736825
}
737826

@@ -749,17 +838,9 @@ namespace ts {
749838
continue;
750839
}
751840

752-
753-
return {
754-
kind: needsBuild(state, status, config) ?
755-
InvalidatedProjectKind.BuildProject :
756-
InvalidatedProjectKind.UpdateBundle,
757-
project,
758-
projectPath,
759-
projectIndex,
760-
config,
761-
buildOrder
762-
};
841+
return needsBuild(state, status, config) ?
842+
createBuildInvalidedProject(state, project, projectPath, projectIndex, config, buildOrder) :
843+
createUpdateBundleProject(state, project, projectPath, projectIndex, config, buildOrder);
763844
}
764845

765846
return undefined;
@@ -1307,46 +1388,19 @@ namespace ts {
13071388
});
13081389
}
13091390

1310-
function needsBuild({ options }: SolutionBuilderState, status: UpToDateStatus, config: ParsedCommandLine) {
1311-
if (status.type !== UpToDateStatusType.OutOfDateWithPrepend || options.force) return true;
1312-
return config.fileNames.length === 0 ||
1313-
!!config.errors.length ||
1314-
!isIncrementalCompilation(config.options);
1315-
}
1316-
1317-
function buildInvalidatedProject(
1318-
state: SolutionBuilderState,
1319-
invalidatedProject: InvalidatedProject,
1320-
cancellationToken?: CancellationToken
1321-
) {
1322-
const { projectPendingBuild } = state;
1323-
if (invalidatedProject.kind === InvalidatedProjectKind.UpdateOutputFileStamps) {
1324-
// Fake that files have been built by updating output file stamps
1325-
const { projectPath, config } = invalidatedProject;
1326-
updateOutputTimestamps(state, config, projectPath);
1327-
projectPendingBuild.delete(projectPath);
1328-
return;
1329-
}
1330-
1331-
const { kind, project, projectPath, projectIndex, config, buildOrder } = invalidatedProject;
1332-
const buildResult = kind === InvalidatedProjectKind.BuildProject ?
1333-
buildSingleProject(state, project, projectPath, config, cancellationToken) : // Actual build
1334-
updateBundle(state, project, projectPath, config, cancellationToken); // Fake that files have been built by manipulating prepend and existing output
1335-
projectPendingBuild.delete(projectPath);
1336-
// Only composite projects can be referenced by other projects
1337-
if (!(buildResult & BuildResultFlags.AnyErrors) && config.options.composite) {
1338-
queueReferencingProjects(state, project, projectPath, projectIndex, buildOrder, !(buildResult & BuildResultFlags.DeclarationOutputUnchanged));
1339-
}
1340-
}
1341-
13421391
function queueReferencingProjects(
13431392
state: SolutionBuilderState,
13441393
project: ResolvedConfigFileName,
13451394
projectPath: ResolvedConfigFilePath,
13461395
projectIndex: number,
1396+
config: ParsedCommandLine,
13471397
buildOrder: readonly ResolvedConfigFileName[],
1348-
declarationOutputChanged: boolean
1398+
buildResult: BuildResultFlags
13491399
) {
1400+
// Queue only if there are no errors
1401+
if (buildResult & BuildResultFlags.AnyErrors) return;
1402+
// Only composite projects can be referenced by other projects
1403+
if (!config.options.composite) return;
13501404
// Always use build order to queue projects
13511405
for (let index = projectIndex + 1; index < buildOrder.length; index++) {
13521406
const nextProject = buildOrder[index];
@@ -1365,7 +1419,7 @@ namespace ts {
13651419
if (status) {
13661420
switch (status.type) {
13671421
case UpToDateStatusType.UpToDate:
1368-
if (!declarationOutputChanged) {
1422+
if (buildResult & BuildResultFlags.DeclarationOutputUnchanged) {
13691423
if (ref.prepend) {
13701424
state.projectStatus.set(nextProjectPath, {
13711425
type: UpToDateStatusType.OutOfDateWithPrepend,
@@ -1382,7 +1436,7 @@ namespace ts {
13821436
// falls through
13831437
case UpToDateStatusType.UpToDateWithUpstreamTypes:
13841438
case UpToDateStatusType.OutOfDateWithPrepend:
1385-
if (declarationOutputChanged) {
1439+
if (!(buildResult & BuildResultFlags.DeclarationOutputUnchanged)) {
13861440
state.projectStatus.set(nextProjectPath, {
13871441
type: UpToDateStatusType.OutOfDateWithUpstream,
13881442
outOfDateOutputFileName: status.type === UpToDateStatusType.OutOfDateWithPrepend ? status.outOfDateOutputFileName : status.oldestOutputFileName,
@@ -1409,7 +1463,7 @@ namespace ts {
14091463
const invalidatedProject = getNextInvalidatedProject(state, getBuildOrder(state));
14101464
if (!invalidatedProject) return undefined;
14111465

1412-
buildInvalidatedProject(state, invalidatedProject, cancellationToken);
1466+
invalidatedProject.done(cancellationToken);
14131467
return {
14141468
project: invalidatedProject.project,
14151469
result: state.diagnostics.has(invalidatedProject.projectPath) ?
@@ -1429,7 +1483,7 @@ namespace ts {
14291483
while (true) {
14301484
const invalidatedProject = getNextInvalidatedProject(state, buildOrder);
14311485
if (!invalidatedProject) break;
1432-
buildInvalidatedProject(state, invalidatedProject, cancellationToken);
1486+
invalidatedProject.done(cancellationToken);
14331487
if (state.diagnostics.has(invalidatedProject.projectPath)) {
14341488
errorProjects++;
14351489
}
@@ -1521,7 +1575,7 @@ namespace ts {
15211575
}
15221576
const invalidatedProject = getNextInvalidatedProject(state, getBuildOrder(state));
15231577
if (invalidatedProject) {
1524-
buildInvalidatedProject(state, invalidatedProject);
1578+
invalidatedProject.done();
15251579
if (state.projectPendingBuild.size) {
15261580
// Schedule next project for build
15271581
if (state.watch && !state.timerToBuildInvalidatedProject) {

0 commit comments

Comments
 (0)