Create api for buildNextProject

This commit is contained in:
Sheetal Nandi 2019-05-02 16:12:29 -07:00
parent 0a255249f6
commit 71b190af61
4 changed files with 80 additions and 11 deletions

View file

@ -260,9 +260,15 @@ namespace ts {
export interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
}
export interface SolutionBuilderResult<T> {
project: ResolvedConfigFileName;
result: T;
}
export interface SolutionBuilder {
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
clean(project?: string): ExitStatus;
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
// Currently used for testing but can be made public if needed:
/*@internal*/ getBuildOrder(): ReadonlyArray<ResolvedConfigFileName>;
@ -401,6 +407,7 @@ namespace ts {
return {
build,
clean,
buildNextProject,
getBuildOrder,
getUpToDateStatusOfProject,
invalidateProject,
@ -1437,10 +1444,7 @@ namespace ts {
return resolvedProject ? createBuildOrder([resolvedProject]) : getBuildOrder();
}
function build(project?: string, cancellationToken?: CancellationToken): ExitStatus {
const buildOrder = getBuildOrderFor(project);
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;
function setupInitialBuild(cancellationToken: CancellationToken | undefined) {
// Set initial build if not already built
if (allProjectBuildPending) {
allProjectBuildPending = false;
@ -1455,6 +1459,27 @@ namespace ts {
cancellationToken.throwIfCancellationRequested();
}
}
}
function buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined {
setupInitialBuild(cancellationToken);
const invalidatedProject = getNextInvalidatedProject(getBuildOrder());
if (!invalidatedProject) return undefined;
buildInvalidatedProject(invalidatedProject, cancellationToken);
return {
project: invalidatedProject.project,
result: diagnostics.has(invalidatedProject.projectPath) ?
ExitStatus.DiagnosticsPresent_OutputsSkipped :
ExitStatus.Success
};
}
function build(project?: string, cancellationToken?: CancellationToken): ExitStatus {
const buildOrder = getBuildOrderFor(project);
if (!buildOrder) return ExitStatus.InvalidProject_OutputsSkipped;
setupInitialBuild(cancellationToken);
let successfulProjects = 0;
let errorProjects = 0;

View file

@ -2,9 +2,10 @@ namespace ts {
describe("unittests:: tsbuild:: on 'sample1' project", () => {
let projFs: vfs.FileSystem;
const { time, tick } = getTime();
const allExpectedOutputs = ["/src/tests/index.js",
"/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map",
"/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts"];
const testsOutputs = ["/src/tests/index.js"];
const logicOutputs = ["/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts"];
const coreOutputs = ["/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map"];
const allExpectedOutputs = [...testsOutputs, ...logicOutputs, ...coreOutputs];
before(() => {
projFs = loadProjectFromDisk("tests/projects/sample1", time);
@ -140,8 +141,8 @@ namespace ts {
builder.build();
const result = builder.clean("/src/logic");
host.assertDiagnosticMessages(/*empty*/);
verifyOutputsPresent(fs, [allExpectedOutputs[0]]);
verifyOutputsAbsent(fs, allExpectedOutputs.slice(1));
verifyOutputsPresent(fs, testsOutputs);
verifyOutputsAbsent(fs, [...logicOutputs, ...coreOutputs]);
assert.equal(result, ExitStatus.Success);
});
@ -334,8 +335,8 @@ namespace ts {
const builder = createSolutionBuilder(host, ["/src/tests"], {});
const result = builder.build("/src/logic");
host.assertDiagnosticMessages(/*empty*/);
verifyOutputsAbsent(fs, [allExpectedOutputs[0]]);
verifyOutputsPresent(fs, allExpectedOutputs.slice(1));
verifyOutputsAbsent(fs, testsOutputs);
verifyOutputsPresent(fs, [...logicOutputs, ...coreOutputs]);
assert.equal(result, ExitStatus.Success);
});
@ -348,6 +349,39 @@ namespace ts {
verifyOutputsAbsent(fs, allExpectedOutputs);
assert.equal(result, ExitStatus.InvalidProject_OutputsSkipped);
});
it("building using buildNextProject", () => {
const fs = projFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/tests"], {});
verifyBuildNextResult({
project: "/src/core/tsconfig.json" as ResolvedConfigFileName,
result: ExitStatus.Success
}, coreOutputs, [...logicOutputs, ...testsOutputs]);
verifyBuildNextResult({
project: "/src/logic/tsconfig.json" as ResolvedConfigFileName,
result: ExitStatus.Success
}, [...coreOutputs, ...logicOutputs], testsOutputs);
verifyBuildNextResult({
project: "/src/tests/tsconfig.json" as ResolvedConfigFileName,
result: ExitStatus.Success
}, allExpectedOutputs, emptyArray);
verifyBuildNextResult(/*expected*/ undefined, allExpectedOutputs, emptyArray);
function verifyBuildNextResult(
expected: SolutionBuilderResult<ExitStatus> | undefined,
presentOutputs: readonly string[],
absentOutputs: readonly string[]
) {
const result = builder.buildNextProject();
assert.deepEqual(result, expected);
verifyOutputsPresent(fs, presentOutputs);
verifyOutputsAbsent(fs, absentOutputs);
}
});
});
describe("downstream-blocked compilations", () => {

View file

@ -4594,9 +4594,14 @@ declare namespace ts {
}
interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
}
interface SolutionBuilderResult<T> {
project: ResolvedConfigFileName;
result: T;
}
interface SolutionBuilder {
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
clean(project?: string): ExitStatus;
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
}
/**
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic

View file

@ -4594,9 +4594,14 @@ declare namespace ts {
}
interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
}
interface SolutionBuilderResult<T> {
project: ResolvedConfigFileName;
result: T;
}
interface SolutionBuilder {
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
clean(project?: string): ExitStatus;
buildNextProject(cancellationToken?: CancellationToken): SolutionBuilderResult<ExitStatus> | undefined;
}
/**
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic