Skip to content

Commit 71b190a

Browse files
committed
Create api for buildNextProject
1 parent 0a25524 commit 71b190a

File tree

4 files changed

+80
-11
lines changed

4 files changed

+80
-11
lines changed

src/compiler/tsbuild.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,15 @@ namespace ts {
260260
export interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
261261
}
262262

263+
export interface SolutionBuilderResult<T> {
264+
project: ResolvedConfigFileName;
265+
result: T;
266+
}
267+
263268
export interface SolutionBuilder {
264269
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
265270
clean(project?: string): ExitStatus;
271+
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
266272

267273
// Currently used for testing but can be made public if needed:
268274
/*@internal*/ getBuildOrder(): ReadonlyArray<ResolvedConfigFileName>;
@@ -401,6 +407,7 @@ namespace ts {
401407
return {
402408
build,
403409
clean,
410+
buildNextProject,
404411
getBuildOrder,
405412
getUpToDateStatusOfProject,
406413
invalidateProject,
@@ -1437,10 +1444,7 @@ namespace ts {
14371444
return resolvedProject ? createBuildOrder([resolvedProject]) : getBuildOrder();
14381445
}
14391446

1440-
function build(project?: string, cancellationToken?: CancellationToken): ExitStatus {
1441-
const buildOrder = getBuildOrderFor(project);
1442-
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;
1443-
1447+
function setupInitialBuild(cancellationToken: CancellationToken | undefined) {
14441448
// Set initial build if not already built
14451449
if (allProjectBuildPending) {
14461450
allProjectBuildPending = false;
@@ -1455,6 +1459,27 @@ namespace ts {
14551459
cancellationToken.throwIfCancellationRequested();
14561460
}
14571461
}
1462+
}
1463+
1464+
function buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined {
1465+
setupInitialBuild(cancellationToken);
1466+
const invalidatedProject = getNextInvalidatedProject(getBuildOrder());
1467+
if (!invalidatedProject) return undefined;
1468+
1469+
buildInvalidatedProject(invalidatedProject, cancellationToken);
1470+
return {
1471+
project: invalidatedProject.project,
1472+
result: diagnostics.has(invalidatedProject.projectPath) ?
1473+
ExitStatus.DiagnosticsPresent_OutputsSkipped :
1474+
ExitStatus.Success
1475+
};
1476+
}
1477+
1478+
function build(project?: string, cancellationToken?: CancellationToken): ExitStatus {
1479+
const buildOrder = getBuildOrderFor(project);
1480+
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;
1481+
1482+
setupInitialBuild(cancellationToken);
14581483

14591484
let successfulProjects = 0;
14601485
let errorProjects = 0;

src/testRunner/unittests/tsbuild/sample.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ namespace ts {
22
describe("unittests:: tsbuild:: on 'sample1' project", () => {
33
let projFs: vfs.FileSystem;
44
const { time, tick } = getTime();
5-
const allExpectedOutputs = ["/src/tests/index.js",
6-
"/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map",
7-
"/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts"];
5+
const testsOutputs = ["/src/tests/index.js"];
6+
const logicOutputs = ["/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts"];
7+
const coreOutputs = ["/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map"];
8+
const allExpectedOutputs = [...testsOutputs, ...logicOutputs, ...coreOutputs];
89

910
before(() => {
1011
projFs = loadProjectFromDisk("tests/projects/sample1", time);
@@ -140,8 +141,8 @@ namespace ts {
140141
builder.build();
141142
const result = builder.clean("/src/logic");
142143
host.assertDiagnosticMessages(/*empty*/);
143-
verifyOutputsPresent(fs, [allExpectedOutputs[0]]);
144-
verifyOutputsAbsent(fs, allExpectedOutputs.slice(1));
144+
verifyOutputsPresent(fs, testsOutputs);
145+
verifyOutputsAbsent(fs, [...logicOutputs, ...coreOutputs]);
145146
assert.equal(result, ExitStatus.Success);
146147
});
147148

@@ -334,8 +335,8 @@ namespace ts {
334335
const builder = createSolutionBuilder(host, ["/src/tests"], {});
335336
const result = builder.build("/src/logic");
336337
host.assertDiagnosticMessages(/*empty*/);
337-
verifyOutputsAbsent(fs, [allExpectedOutputs[0]]);
338-
verifyOutputsPresent(fs, allExpectedOutputs.slice(1));
338+
verifyOutputsAbsent(fs, testsOutputs);
339+
verifyOutputsPresent(fs, [...logicOutputs, ...coreOutputs]);
339340
assert.equal(result, ExitStatus.Success);
340341
});
341342

@@ -348,6 +349,39 @@ namespace ts {
348349
verifyOutputsAbsent(fs, allExpectedOutputs);
349350
assert.equal(result, ExitStatus.InvalidProject_OutputsSkipped);
350351
});
352+
353+
it("building using buildNextProject", () => {
354+
const fs = projFs.shadow();
355+
const host = new fakes.SolutionBuilderHost(fs);
356+
const builder = createSolutionBuilder(host, ["/src/tests"], {});
357+
verifyBuildNextResult({
358+
project: "/src/core/tsconfig.json" as ResolvedConfigFileName,
359+
result: ExitStatus.Success
360+
}, coreOutputs, [...logicOutputs, ...testsOutputs]);
361+
362+
verifyBuildNextResult({
363+
project: "/src/logic/tsconfig.json" as ResolvedConfigFileName,
364+
result: ExitStatus.Success
365+
}, [...coreOutputs, ...logicOutputs], testsOutputs);
366+
367+
verifyBuildNextResult({
368+
project: "/src/tests/tsconfig.json" as ResolvedConfigFileName,
369+
result: ExitStatus.Success
370+
}, allExpectedOutputs, emptyArray);
371+
372+
verifyBuildNextResult(/*expected*/ undefined, allExpectedOutputs, emptyArray);
373+
374+
function verifyBuildNextResult(
375+
expected: SolutionBuilderResult<ExitStatus> | undefined,
376+
presentOutputs: readonly string[],
377+
absentOutputs: readonly string[]
378+
) {
379+
const result = builder.buildNextProject();
380+
assert.deepEqual(result, expected);
381+
verifyOutputsPresent(fs, presentOutputs);
382+
verifyOutputsAbsent(fs, absentOutputs);
383+
}
384+
});
351385
});
352386

353387
describe("downstream-blocked compilations", () => {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4594,9 +4594,14 @@ declare namespace ts {
45944594
}
45954595
interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
45964596
}
4597+
interface SolutionBuilderResult<T> {
4598+
project: ResolvedConfigFileName;
4599+
result: T;
4600+
}
45974601
interface SolutionBuilder {
45984602
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
45994603
clean(project?: string): ExitStatus;
4604+
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
46004605
}
46014606
/**
46024607
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic

tests/baselines/reference/api/typescript.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4594,9 +4594,14 @@ declare namespace ts {
45944594
}
45954595
interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
45964596
}
4597+
interface SolutionBuilderResult<T> {
4598+
project: ResolvedConfigFileName;
4599+
result: T;
4600+
}
45974601
interface SolutionBuilder {
45984602
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
45994603
clean(project?: string): ExitStatus;
4604+
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
46004605
}
46014606
/**
46024607
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic

0 commit comments

Comments
 (0)