mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Make API to build project and wire cancellation token
This commit is contained in:
+108
-45
@@ -255,7 +255,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface SolutionBuilder {
|
||||
buildAllProjects(): ExitStatus;
|
||||
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
|
||||
cleanAllProjects(): ExitStatus;
|
||||
|
||||
// Currently used for testing but can be made public if needed:
|
||||
@@ -264,14 +264,21 @@ namespace ts {
|
||||
// Testing only
|
||||
/*@internal*/ getUpToDateStatusOfProject(project: string): UpToDateStatus;
|
||||
/*@internal*/ invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel): void;
|
||||
/*@internal*/ buildInvalidatedProject(): void;
|
||||
/*@internal*/ buildNextInvalidatedProject(): void;
|
||||
}
|
||||
|
||||
export interface SolutionBuilderWithWatch {
|
||||
buildAllProjects(): ExitStatus;
|
||||
build(project?: string, cancellationToken?: CancellationToken): ExitStatus;
|
||||
/*@internal*/ startWatching(): void;
|
||||
}
|
||||
|
||||
interface InvalidatedProject {
|
||||
project: ResolvedConfigFileName;
|
||||
projectPath: ResolvedConfigFilePath;
|
||||
reloadLevel: ConfigFileProgramReloadLevel;
|
||||
projectIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a function that reports watch status by writing to the system and handles the formating of the diagnostic
|
||||
*/
|
||||
@@ -386,18 +393,22 @@ namespace ts {
|
||||
const allWatchedInputFiles = createMap() as ConfigFileMap<Map<FileWatcher>>;
|
||||
const allWatchedConfigFiles = createMap() as ConfigFileMap<FileWatcher>;
|
||||
|
||||
let allProjectBuildPending = true;
|
||||
let needsSummary = true;
|
||||
// let watchAllProjectsPending = watch;
|
||||
|
||||
return watch ?
|
||||
{
|
||||
buildAllProjects,
|
||||
build,
|
||||
startWatching
|
||||
} :
|
||||
{
|
||||
buildAllProjects,
|
||||
build,
|
||||
cleanAllProjects,
|
||||
getBuildOrder,
|
||||
getUpToDateStatusOfProject,
|
||||
invalidateProject,
|
||||
buildInvalidatedProject,
|
||||
buildNextInvalidatedProject,
|
||||
};
|
||||
|
||||
function toPath(fileName: string) {
|
||||
@@ -800,6 +811,7 @@ namespace ts {
|
||||
configFileCache.delete(resolved);
|
||||
buildOrder = undefined;
|
||||
}
|
||||
needsSummary = true;
|
||||
clearProjectStatus(resolved);
|
||||
addProjToQueue(resolved, reloadLevel);
|
||||
enableCache();
|
||||
@@ -823,16 +835,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getNextInvalidatedProject() {
|
||||
Debug.assert(hasPendingInvalidatedProjects());
|
||||
return forEach(getBuildOrder(), (project, projectIndex) => {
|
||||
const projectPath = toResolvedConfigFilePath(project);
|
||||
const reloadLevel = projectPendingBuild.get(projectPath);
|
||||
if (reloadLevel !== undefined) {
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return { project, projectPath, reloadLevel, projectIndex };
|
||||
}
|
||||
});
|
||||
function getNextInvalidatedProject(buildOrder: readonly ResolvedConfigFileName[]): InvalidatedProject | undefined {
|
||||
return hasPendingInvalidatedProjects() ?
|
||||
forEach(buildOrder, (project, projectIndex) => {
|
||||
const projectPath = toResolvedConfigFilePath(project);
|
||||
const reloadLevel = projectPendingBuild.get(projectPath);
|
||||
if (reloadLevel !== undefined) {
|
||||
return { project, projectPath, reloadLevel, projectIndex };
|
||||
}
|
||||
}) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function hasPendingInvalidatedProjects() {
|
||||
@@ -846,18 +858,19 @@ namespace ts {
|
||||
if (timerToBuildInvalidatedProject) {
|
||||
hostWithWatch.clearTimeout(timerToBuildInvalidatedProject);
|
||||
}
|
||||
timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildInvalidatedProject, 250);
|
||||
timerToBuildInvalidatedProject = hostWithWatch.setTimeout(buildNextInvalidatedProject, 250);
|
||||
}
|
||||
|
||||
function buildInvalidatedProject() {
|
||||
function buildNextInvalidatedProject() {
|
||||
timerToBuildInvalidatedProject = undefined;
|
||||
if (reportFileChangeDetected) {
|
||||
reportFileChangeDetected = false;
|
||||
projectErrorsReported.clear();
|
||||
reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation);
|
||||
}
|
||||
if (hasPendingInvalidatedProjects()) {
|
||||
buildNextInvalidatedProject();
|
||||
const invalidatedProject = getNextInvalidatedProject(getBuildOrder());
|
||||
if (invalidatedProject) {
|
||||
buildInvalidatedProject(invalidatedProject);
|
||||
if (hasPendingInvalidatedProjects()) {
|
||||
if (watch && !timerToBuildInvalidatedProject) {
|
||||
scheduleBuildInvalidatedProject();
|
||||
@@ -872,6 +885,7 @@ namespace ts {
|
||||
|
||||
function reportErrorSummary() {
|
||||
if (watch || host.reportErrorSummary) {
|
||||
needsSummary = false;
|
||||
// Report errors from the other projects
|
||||
getBuildOrder().forEach(project => {
|
||||
const projectPath = toResolvedConfigFilePath(project);
|
||||
@@ -890,11 +904,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildNextInvalidatedProject() {
|
||||
const { project, projectPath, reloadLevel, projectIndex } = getNextInvalidatedProject()!;
|
||||
function buildInvalidatedProject({ project, projectPath, reloadLevel, projectIndex }: InvalidatedProject, cancellationToken?: CancellationToken) {
|
||||
const config = parseConfigFile(project, projectPath);
|
||||
if (!config) {
|
||||
reportParseConfigFileDiagnostic(projectPath);
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -920,6 +934,7 @@ namespace ts {
|
||||
// In a dry build, inform the user of this fact
|
||||
reportStatus(Diagnostics.Project_0_is_up_to_date, project);
|
||||
}
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -927,24 +942,28 @@ namespace ts {
|
||||
reportAndStoreErrors(projectPath, config.errors);
|
||||
// Fake that files have been built by updating output file stamps
|
||||
updateOutputTimestamps(config, projectPath);
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status.type === UpToDateStatusType.UpstreamBlocked) {
|
||||
reportAndStoreErrors(projectPath, config.errors);
|
||||
if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, project, status.upstreamProjectName);
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status.type === UpToDateStatusType.ContainerOnly) {
|
||||
reportAndStoreErrors(projectPath, config.errors);
|
||||
// Do nothing
|
||||
projectPendingBuild.delete(projectPath);
|
||||
return;
|
||||
}
|
||||
|
||||
const buildResult = needsBuild(status, config) ?
|
||||
buildSingleProject(project, projectPath) : // Actual build
|
||||
updateBundle(project, projectPath); // Fake that files have been built by manipulating prepend and existing output
|
||||
buildSingleProject(project, projectPath, cancellationToken) : // Actual build
|
||||
updateBundle(project, projectPath, cancellationToken); // Fake that files have been built by manipulating prepend and existing output
|
||||
projectPendingBuild.delete(projectPath);
|
||||
// Only composite projects can be referenced by other projects
|
||||
if (!(buildResult & BuildResultFlags.AnyErrors) && config.options.composite) {
|
||||
queueReferencingProjects(project, projectPath, projectIndex, !(buildResult & BuildResultFlags.DeclarationOutputUnchanged));
|
||||
@@ -1050,7 +1069,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildSingleProject(proj: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath): BuildResultFlags {
|
||||
function buildSingleProject(proj: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, cancellationToken: CancellationToken | undefined): BuildResultFlags {
|
||||
if (options.dry) {
|
||||
reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj);
|
||||
return BuildResultFlags.Success;
|
||||
@@ -1112,15 +1131,15 @@ namespace ts {
|
||||
// Don't emit anything in the presence of syntactic errors or options diagnostics
|
||||
const syntaxDiagnostics = [
|
||||
...program.getConfigFileParsingDiagnostics(),
|
||||
...program.getOptionsDiagnostics(),
|
||||
...program.getGlobalDiagnostics(),
|
||||
...program.getSyntacticDiagnostics()];
|
||||
...program.getOptionsDiagnostics(cancellationToken),
|
||||
...program.getGlobalDiagnostics(cancellationToken),
|
||||
...program.getSyntacticDiagnostics(/*sourceFile*/ undefined, cancellationToken)];
|
||||
if (syntaxDiagnostics.length) {
|
||||
return buildErrors(syntaxDiagnostics, BuildResultFlags.SyntaxErrors, "Syntactic");
|
||||
}
|
||||
|
||||
// Same as above but now for semantic diagnostics
|
||||
const semanticDiagnostics = program.getSemanticDiagnostics();
|
||||
const semanticDiagnostics = program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken);
|
||||
if (semanticDiagnostics.length) {
|
||||
return buildErrors(semanticDiagnostics, BuildResultFlags.TypeErrors, "Semantic");
|
||||
}
|
||||
@@ -1132,7 +1151,14 @@ namespace ts {
|
||||
let declDiagnostics: Diagnostic[] | undefined;
|
||||
const reportDeclarationDiagnostics = (d: Diagnostic) => (declDiagnostics || (declDiagnostics = [])).push(d);
|
||||
const outputFiles: OutputFile[] = [];
|
||||
emitFilesAndReportErrors(program, reportDeclarationDiagnostics, /*writeFileName*/ undefined, /*reportSummary*/ undefined, (name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }));
|
||||
emitFilesAndReportErrors(
|
||||
program,
|
||||
reportDeclarationDiagnostics,
|
||||
/*writeFileName*/ undefined,
|
||||
/*reportSummary*/ undefined,
|
||||
(name, text, writeByteOrderMark) => outputFiles.push({ name, text, writeByteOrderMark }),
|
||||
cancellationToken
|
||||
);
|
||||
// Don't emit .d.ts if there are decl file errors
|
||||
if (declDiagnostics) {
|
||||
program.restoreState();
|
||||
@@ -1221,7 +1247,7 @@ namespace ts {
|
||||
return readBuilderProgram(parsed.options, readFileWithCache) as any as T;
|
||||
}
|
||||
|
||||
function updateBundle(proj: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath): BuildResultFlags {
|
||||
function updateBundle(proj: ResolvedConfigFileName, resolvedPath: ResolvedConfigFilePath, cancellationToken: CancellationToken | undefined): BuildResultFlags {
|
||||
if (options.dry) {
|
||||
reportStatus(Diagnostics.A_non_dry_build_would_update_output_of_project_0, proj);
|
||||
return BuildResultFlags.Success;
|
||||
@@ -1241,7 +1267,7 @@ namespace ts {
|
||||
});
|
||||
if (isString(outputFiles)) {
|
||||
reportStatus(Diagnostics.Cannot_update_output_of_project_0_because_there_was_error_reading_file_1, proj, relName(outputFiles));
|
||||
return buildSingleProject(proj, resolvedPath);
|
||||
return buildSingleProject(proj, resolvedPath, cancellationToken);
|
||||
}
|
||||
|
||||
// Actual Emit
|
||||
@@ -1403,21 +1429,58 @@ namespace ts {
|
||||
cacheState = undefined;
|
||||
}
|
||||
|
||||
function buildAllProjects(): ExitStatus {
|
||||
if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); }
|
||||
enableCache();
|
||||
function build(project?: string, cancellationToken?: CancellationToken): ExitStatus {
|
||||
// Set initial build if not already built
|
||||
if (allProjectBuildPending) {
|
||||
allProjectBuildPending = false;
|
||||
if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); }
|
||||
enableCache();
|
||||
const buildOrder = getBuildOrder();
|
||||
reportBuildQueue(buildOrder);
|
||||
buildOrder.forEach(configFileName =>
|
||||
projectPendingBuild.set(toResolvedConfigFilePath(configFileName), ConfigFileProgramReloadLevel.None));
|
||||
|
||||
const buildOrder = getBuildOrder();
|
||||
reportBuildQueue(buildOrder);
|
||||
buildOrder.forEach(configFileName =>
|
||||
projectPendingBuild.set(toResolvedConfigFilePath(configFileName), ConfigFileProgramReloadLevel.None));
|
||||
|
||||
while (hasPendingInvalidatedProjects()) {
|
||||
buildNextInvalidatedProject();
|
||||
if (cancellationToken) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
reportErrorSummary();
|
||||
disableCache();
|
||||
return diagnostics.size ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
|
||||
|
||||
let successfulProjects = 0;
|
||||
let errorProjects = 0;
|
||||
const resolvedProject = project && resolveProjectName(project);
|
||||
if (resolvedProject) {
|
||||
const projectPath = toResolvedConfigFilePath(resolvedProject);
|
||||
const projectIndex = findIndex(
|
||||
getBuildOrder(),
|
||||
configFileName => toResolvedConfigFilePath(configFileName) === projectPath
|
||||
);
|
||||
if (projectIndex === -1) return ExitStatus.InvalidProject_OutputsSkipped;
|
||||
}
|
||||
const buildOrder = resolvedProject ? createBuildOrder([resolvedProject]) : getBuildOrder();
|
||||
while (true) {
|
||||
const invalidatedProject = getNextInvalidatedProject(buildOrder);
|
||||
if (!invalidatedProject) {
|
||||
if (needsSummary) {
|
||||
disableCache();
|
||||
reportErrorSummary();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buildInvalidatedProject(invalidatedProject, cancellationToken);
|
||||
if (diagnostics.has(invalidatedProject.projectPath)) {
|
||||
errorProjects++;
|
||||
}
|
||||
else {
|
||||
successfulProjects++;
|
||||
}
|
||||
}
|
||||
|
||||
return errorProjects ?
|
||||
successfulProjects ?
|
||||
ExitStatus.DiagnosticsPresent_OutputsGenerated :
|
||||
ExitStatus.DiagnosticsPresent_OutputsSkipped :
|
||||
ExitStatus.Success;
|
||||
}
|
||||
|
||||
function needsBuild(status: UpToDateStatus, config: ParsedCommandLine) {
|
||||
|
||||
@@ -3053,6 +3053,9 @@ namespace ts {
|
||||
|
||||
// Diagnostics were produced and outputs were generated in spite of them.
|
||||
DiagnosticsPresent_OutputsGenerated = 2,
|
||||
|
||||
// When build skipped because passed in project is invalid
|
||||
InvalidProject_OutputsSkipped = 3,
|
||||
}
|
||||
|
||||
export interface EmitResult {
|
||||
|
||||
+18
-11
@@ -113,12 +113,12 @@ namespace ts {
|
||||
getCurrentDirectory(): string;
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getSourceFiles(): ReadonlyArray<SourceFile>;
|
||||
getSyntacticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getOptionsDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getGlobalDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getSemanticDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
|
||||
getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic>;
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
|
||||
}
|
||||
|
||||
export function listFiles(program: ProgramToEmitFilesAndReportErrors, writeFileName: (s: string) => void) {
|
||||
@@ -132,25 +132,32 @@ namespace ts {
|
||||
/**
|
||||
* Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
|
||||
*/
|
||||
export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary, writeFile?: WriteFileCallback) {
|
||||
export function emitFilesAndReportErrors(
|
||||
program: ProgramToEmitFilesAndReportErrors,
|
||||
reportDiagnostic: DiagnosticReporter,
|
||||
writeFileName?: (s: string) => void,
|
||||
reportSummary?: ReportEmitErrorSummary,
|
||||
writeFile?: WriteFileCallback,
|
||||
cancellationToken?: CancellationToken
|
||||
) {
|
||||
// First get and report any syntactic errors.
|
||||
const diagnostics = program.getConfigFileParsingDiagnostics().slice();
|
||||
const configFileParsingDiagnosticsLength = diagnostics.length;
|
||||
addRange(diagnostics, program.getSyntacticDiagnostics());
|
||||
addRange(diagnostics, program.getSyntacticDiagnostics(/*sourceFile*/ undefined, cancellationToken));
|
||||
|
||||
// If we didn't have any syntactic errors, then also try getting the global and
|
||||
// semantic errors.
|
||||
if (diagnostics.length === configFileParsingDiagnosticsLength) {
|
||||
addRange(diagnostics, program.getOptionsDiagnostics());
|
||||
addRange(diagnostics, program.getGlobalDiagnostics());
|
||||
addRange(diagnostics, program.getOptionsDiagnostics(cancellationToken));
|
||||
addRange(diagnostics, program.getGlobalDiagnostics(cancellationToken));
|
||||
|
||||
if (diagnostics.length === configFileParsingDiagnosticsLength) {
|
||||
addRange(diagnostics, program.getSemanticDiagnostics());
|
||||
addRange(diagnostics, program.getSemanticDiagnostics(/*sourceFile*/ undefined, cancellationToken));
|
||||
}
|
||||
}
|
||||
|
||||
// Emit and report any errors we ran into.
|
||||
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(/*targetSourceFile*/ undefined, writeFile);
|
||||
const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken);
|
||||
addRange(diagnostics, emitDiagnostics);
|
||||
|
||||
sortAndDeduplicateDiagnostics(diagnostics).forEach(reportDiagnostic);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ts {
|
||||
const builder = createSolutionBuilder(host, ["/src/no-references"], { dry: false, force: false, verbose: false });
|
||||
|
||||
host.clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages([Diagnostics.The_files_list_in_config_file_0_is_empty, "/src/no-references/tsconfig.json"]);
|
||||
|
||||
// Check for outputs to not be written.
|
||||
@@ -29,7 +29,7 @@ namespace ts {
|
||||
const builder = createSolutionBuilder(host, ["/src/with-references"], { dry: false, force: false, verbose: false });
|
||||
|
||||
host.clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
|
||||
// Check for outputs to be written.
|
||||
|
||||
@@ -172,7 +172,7 @@ declare const console: { log(msg: any): void; };`;
|
||||
}
|
||||
return originalReadFile.call(host, path);
|
||||
};
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
generateSourceMapBaselineFiles(fs, expectedMapFileNames);
|
||||
generateBuildInfoSectionBaselineFiles(fs, expectedBuildInfoFilesForSectionBaselines || emptyArray);
|
||||
fs.makeReadonly();
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tsconfig.json"], {});
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
[Diagnostics.The_specified_path_does_not_exist_Colon_0, "/src/foobar.json"],
|
||||
[Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, "/src/tsconfig.first.json", "[\"**/*\"]", "[]"],
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace ts {
|
||||
];
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
// Verify they exist
|
||||
for (const output of expectedOutputs) {
|
||||
@@ -389,7 +389,7 @@ namespace ts {
|
||||
];
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
// Verify they exist
|
||||
for (const output of expectedOutputs) {
|
||||
@@ -399,7 +399,7 @@ namespace ts {
|
||||
host.clearDiagnostics();
|
||||
host.deleteFile(outputFiles[project.first][ext.buildinfo]);
|
||||
builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, relSources[project.first][source.config], relOutputFiles[project.first][ext.buildinfo]],
|
||||
@@ -416,7 +416,7 @@ namespace ts {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
replaceText(fs, sources[project.third][source.config], `"composite": true,`, "");
|
||||
const builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
// Verify they exist - without tsbuildinfo for third project
|
||||
for (const output of expectedOutputFiles.slice(0, expectedOutputFiles.length - 2)) {
|
||||
@@ -429,12 +429,12 @@ namespace ts {
|
||||
const fs = outFileFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
host.clearDiagnostics();
|
||||
builder = createSolutionBuilder(host);
|
||||
changeCompilerVersion(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relSources[project.first][source.config], fakes.version, version],
|
||||
@@ -454,7 +454,7 @@ namespace ts {
|
||||
// Build with command line incremental
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, { incremental: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
@@ -462,7 +462,7 @@ namespace ts {
|
||||
// Make non incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[project.first][source.ts][part.one], "console.log(s);");
|
||||
builder = createSolutionBuilder(host, { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[project.first][source.config], relOutputFiles[project.first][ext.js], relSources[project.first][source.ts][part.one]],
|
||||
[Diagnostics.Building_project_0, sources[project.first][source.config]],
|
||||
@@ -476,7 +476,7 @@ namespace ts {
|
||||
// Make incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[project.first][source.ts][part.one], "console.log(s);");
|
||||
builder = createSolutionBuilder(host, { verbose: true, incremental: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
// Builds completely because tsbuildinfo is old.
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
@@ -489,6 +489,23 @@ namespace ts {
|
||||
host.clearDiagnostics();
|
||||
});
|
||||
|
||||
it("builds till project specified", () => {
|
||||
const fs = outFileFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, { verbose: false });
|
||||
const result = builder.build(sources[project.second][source.config]);
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
// First and Third is not built
|
||||
for (const output of [...outputFiles[project.first], ...outputFiles[project.third]]) {
|
||||
assert.isFalse(fs.existsSync(output), `Expect file ${output} to not exist`);
|
||||
}
|
||||
// second is built
|
||||
for (const output of outputFiles[project.second]) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
}
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
});
|
||||
|
||||
describe("Prepend output with .tsbuildinfo", () => {
|
||||
// Prologues
|
||||
describe("Prologues", () => {
|
||||
@@ -904,7 +921,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[project.first][source.config], relSources[project.second][source.config], relSources[project.third][source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, relSources[project.first][source.config], "src/first/first_PART1.js"],
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/src/main", "/src/src/other"], {});
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
@@ -39,7 +39,7 @@ namespace ts {
|
||||
replaceText(fs, "/src/tsconfig.base.json", `"rootDir": "./src/",`, "");
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/src/main"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/src/other/tsconfig.json", "src/src/main/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/src/other/tsconfig.json", "src/dist/other.js"],
|
||||
@@ -75,7 +75,7 @@ namespace ts {
|
||||
}));
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/src/main"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/src/other/tsconfig.json", "src/src/main/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/src/other/tsconfig.json", "src/dist/other.js"],
|
||||
@@ -112,7 +112,7 @@ namespace ts {
|
||||
}));
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/src/main/tsconfig.main.json"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/src/other/tsconfig.other.json", "src/src/main/tsconfig.main.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/src/other/tsconfig.other.json", "src/dist/other.js"],
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ts {
|
||||
function verifyProjectWithResolveJsonModuleWithFs(fs: vfs.FileSystem, configFile: string, allExpectedOutputs: ReadonlyArray<string>, ...expectedDiagnosticMessages: fakes.ExpectedDiagnostic[]) {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, [configFile], { dry: false, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...expectedDiagnosticMessages);
|
||||
if (!expectedDiagnosticMessages.length) {
|
||||
// Check for outputs. Not an exhaustive list
|
||||
@@ -65,7 +65,7 @@ export default hello.hello`);
|
||||
replaceText(fs, configFile, `"composite": true,`, `"composite": true, "sourceMap": true,`);
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(configFile),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, configFile, "src/dist/src/index.js"],
|
||||
@@ -77,7 +77,7 @@ export default hello.hello`);
|
||||
host.clearDiagnostics();
|
||||
builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
tick();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(configFile),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFile, "src/src/index.ts", "src/dist/src/index.js"]
|
||||
@@ -90,7 +90,7 @@ export default hello.hello`);
|
||||
replaceText(fs, configFile, `"outDir": "dist",`, "");
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(configFile),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, configFile, "src/src/index.js"],
|
||||
@@ -102,7 +102,7 @@ export default hello.hello`);
|
||||
host.clearDiagnostics();
|
||||
builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
tick();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(configFile),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFile, "src/src/index.ts", "src/src/index.js"]
|
||||
@@ -129,7 +129,7 @@ export default hello.hello`);
|
||||
const mainConfigFile = "src/main/tsconfig.json";
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(stringsConfigFile, mainConfigFile, configFile),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, stringsConfigFile, "src/strings/tsconfig.tsbuildinfo"],
|
||||
@@ -141,7 +141,7 @@ export default hello.hello`);
|
||||
host.clearDiagnostics();
|
||||
builder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
tick();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(stringsConfigFile, mainConfigFile, configFile),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, stringsConfigFile, "src/strings/foo.json", "src/strings/tsconfig.tsbuildinfo"],
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ts {
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
|
||||
host.clearDiagnostics();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
|
||||
// Check for outputs. Not an exhaustive list
|
||||
@@ -39,7 +39,7 @@ namespace ts {
|
||||
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/", "/logic/outDir/"));
|
||||
// Check for outputs. Not an exhaustive list
|
||||
@@ -57,7 +57,7 @@ namespace ts {
|
||||
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
const expectedOutputs = allExpectedOutputs.map(f => f.replace("/logic/index.d.ts", "/logic/out/decls/index.d.ts"));
|
||||
// Check for outputs. Not an exhaustive list
|
||||
@@ -71,7 +71,7 @@ namespace ts {
|
||||
replaceText(fs, "/src/core/tsconfig.json", `"composite": true,`, "");
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/core"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
@@ -88,7 +88,7 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
[Diagnostics.A_non_dry_build_would_build_project_0, "/src/core/tsconfig.json"],
|
||||
[Diagnostics.A_non_dry_build_would_build_project_0, "/src/logic/tsconfig.json"],
|
||||
@@ -106,12 +106,12 @@ namespace ts {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
tick();
|
||||
|
||||
host.clearDiagnostics();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { dry: true, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
[Diagnostics.Project_0_is_up_to_date, "/src/core/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_up_to_date, "/src/logic/tsconfig.json"],
|
||||
@@ -126,7 +126,7 @@ namespace ts {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
// Verify they exist
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
@@ -146,15 +146,16 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: true, verbose: false });
|
||||
builder.buildAllProjects();
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: true, verbose: false });
|
||||
builder.build();
|
||||
let currentTime = time();
|
||||
checkOutputTimestamps(currentTime);
|
||||
|
||||
tick();
|
||||
Debug.assert(time() !== currentTime, "Time moves on");
|
||||
currentTime = time();
|
||||
builder.buildAllProjects();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: true, verbose: false });
|
||||
builder.build();
|
||||
checkOutputTimestamps(currentTime);
|
||||
|
||||
function checkOutputTimestamps(expected: number) {
|
||||
@@ -172,7 +173,7 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { ...(opts || {}), verbose: true });
|
||||
@@ -183,7 +184,7 @@ namespace ts {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
@@ -198,7 +199,7 @@ namespace ts {
|
||||
// All three projects are up to date
|
||||
it("Detects that all projects are up to date", () => {
|
||||
const { host, builder } = initializeWithBuild();
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
@@ -211,7 +212,7 @@ namespace ts {
|
||||
it("Only builds the leaf node project", () => {
|
||||
const { fs, host, builder } = initializeWithBuild();
|
||||
fs.writeFileSync("/src/tests/index.ts", "const m = 10;");
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
@@ -225,7 +226,7 @@ namespace ts {
|
||||
it("Detects type-only changes in upstream projects", () => {
|
||||
const { fs, host, builder } = initializeWithBuild();
|
||||
replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET");
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
@@ -242,7 +243,7 @@ namespace ts {
|
||||
it("rebuilds completely when version in tsbuildinfo doesnt match ts version", () => {
|
||||
const { host, builder } = initializeWithBuild();
|
||||
changeCompilerVersion(host);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, "src/core/tsconfig.json", fakes.version, version],
|
||||
@@ -256,7 +257,7 @@ namespace ts {
|
||||
|
||||
it("rebuilds from start if --f is passed", () => {
|
||||
const { host, builder } = initializeWithBuild({ force: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
@@ -271,7 +272,7 @@ namespace ts {
|
||||
it("rebuilds when tsconfig changes", () => {
|
||||
const { fs, host, builder } = initializeWithBuild();
|
||||
replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es3"`);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
@@ -287,7 +288,7 @@ namespace ts {
|
||||
replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`);
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
@@ -301,7 +302,7 @@ namespace ts {
|
||||
tick();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: {} }));
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
@@ -310,6 +311,31 @@ namespace ts {
|
||||
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
|
||||
);
|
||||
});
|
||||
|
||||
it("builds till project specified", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
const result = builder.build("/src/logic");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
assert.isFalse(fs.existsSync(allExpectedOutputs[0]), `Expect file ${allExpectedOutputs[0]} to not exist`);
|
||||
for (const output of allExpectedOutputs.slice(1)) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
}
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
});
|
||||
|
||||
it("building project in not build order doesnt throw error", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
const result = builder.build("/src/logic2");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert.isFalse(fs.existsSync(output), `Expect file ${output} to not exist`);
|
||||
}
|
||||
assert.equal(result, ExitStatus.InvalidProject_OutputsSkipped);
|
||||
});
|
||||
});
|
||||
|
||||
describe("downstream-blocked compilations", () => {
|
||||
@@ -320,7 +346,7 @@ namespace ts {
|
||||
|
||||
// Induce an error in the middle project
|
||||
replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
@@ -340,7 +366,7 @@ namespace ts {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
|
||||
// Update a timestamp in the middle project
|
||||
@@ -366,7 +392,7 @@ export class cNew {}`);
|
||||
// Rebuild this project
|
||||
tick();
|
||||
builder.invalidateProject("/src/logic");
|
||||
builder.buildInvalidatedProject();
|
||||
builder.buildNextInvalidatedProject();
|
||||
// The file should be updated
|
||||
assert.isTrue(writtenFiles.has("/src/logic/index.js"), "JS file should have been rebuilt");
|
||||
assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt");
|
||||
@@ -376,7 +402,7 @@ export class cNew {}`);
|
||||
|
||||
// Build downstream projects should update 'tests', but not 'core'
|
||||
tick();
|
||||
builder.buildInvalidatedProject();
|
||||
builder.buildNextInvalidatedProject();
|
||||
if (expectedToWriteTests) {
|
||||
assert.isTrue(writtenFiles.has("/src/tests/index.js"), "Downstream JS file should have been rebuilt");
|
||||
}
|
||||
@@ -394,7 +420,7 @@ export class cNew {}`);
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { listFiles: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
assert.deepEqual(host.traces, [
|
||||
"/lib/lib.d.ts",
|
||||
"/src/core/anotherModule.ts",
|
||||
@@ -421,7 +447,7 @@ export class cNew {}`);
|
||||
const fs = projFs.shadow();
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { listEmittedFiles: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
assert.deepEqual(host.traces, [
|
||||
"TSFILE: /src/core/anotherModule.js",
|
||||
"TSFILE: /src/core/anotherModule.d.ts.map",
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ts {
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
modifyDiskLayout(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tsconfig.c.json"], { listFiles: true });
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...expectedDiagnostics);
|
||||
for (const output of allExpectedOutputs) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace ts.tscWatch {
|
||||
function createSolutionBuilderWithWatch(system: TsBuildWatchSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
|
||||
const host = createSolutionBuilderWithWatchHost(system);
|
||||
const solutionBuilder = ts.createSolutionBuilderWithWatch(host, rootNames, defaultOptions || { watch: true });
|
||||
solutionBuilder.buildAllProjects();
|
||||
solutionBuilder.build();
|
||||
solutionBuilder.startWatching();
|
||||
return solutionBuilder;
|
||||
}
|
||||
@@ -608,7 +608,7 @@ let x: string = 10;`);
|
||||
// Build the composite project
|
||||
const host = createTsBuildWatchSystem(allFiles, { currentDirectory });
|
||||
const solutionBuilder = createSolutionBuilder(host, [solutionBuilderconfig], {});
|
||||
solutionBuilder.buildAllProjects();
|
||||
solutionBuilder.build();
|
||||
const outputFileStamps = getOutputFileStamps(host);
|
||||
for (const stamp of outputFileStamps) {
|
||||
assert.isDefined(stamp[1], `${stamp[0]} expected to be present`);
|
||||
@@ -723,7 +723,7 @@ let x: string = 10;`);
|
||||
function foo() {
|
||||
}`);
|
||||
solutionBuilder.invalidateProject(`${project}/${SubProject.logic}`);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
solutionBuilder.buildNextInvalidatedProject();
|
||||
|
||||
// not ideal, but currently because of d.ts but no new file is written
|
||||
// There will be timeout queued even though file contents are same
|
||||
@@ -736,7 +736,7 @@ function foo() {
|
||||
export function gfoo() {
|
||||
}`);
|
||||
solutionBuilder.invalidateProject(logic[0].path);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
solutionBuilder.buildNextInvalidatedProject();
|
||||
}, expectedProgramFiles);
|
||||
});
|
||||
|
||||
@@ -747,7 +747,7 @@ export function gfoo() {
|
||||
references: [{ path: "../core" }]
|
||||
}));
|
||||
solutionBuilder.invalidateProject(logic[0].path, ConfigFileProgramReloadLevel.Full);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
solutionBuilder.buildNextInvalidatedProject();
|
||||
}, [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
|
||||
});
|
||||
});
|
||||
@@ -967,7 +967,7 @@ export function gfoo() {
|
||||
export function gfoo() {
|
||||
}`);
|
||||
solutionBuilder.invalidateProject(bTsconfig.path);
|
||||
solutionBuilder.buildInvalidatedProject();
|
||||
solutionBuilder.buildNextInvalidatedProject();
|
||||
},
|
||||
emptyArray,
|
||||
expectedProgramFiles,
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ts.projectSystem {
|
||||
|
||||
// ts build should succeed
|
||||
const solutionBuilder = tscWatch.createSolutionBuilder(host, rootNames, {});
|
||||
solutionBuilder.buildAllProjects();
|
||||
solutionBuilder.build();
|
||||
assert.equal(host.getOutput().length, 0);
|
||||
|
||||
return host;
|
||||
|
||||
+2
-2
@@ -216,7 +216,7 @@ namespace ts {
|
||||
updateCreateProgram(buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(program.getProgram());
|
||||
const builder = createSolutionBuilderWithWatch(buildHost, projects, buildOptions);
|
||||
builder.buildAllProjects();
|
||||
builder.build();
|
||||
return builder.startWatching();
|
||||
}
|
||||
else {
|
||||
@@ -224,7 +224,7 @@ namespace ts {
|
||||
updateCreateProgram(buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = program => reportStatistics(program.getProgram());
|
||||
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
|
||||
return sys.exit(buildOptions.clean ? builder.cleanAllProjects() : builder.buildAllProjects());
|
||||
return sys.exit(buildOptions.clean ? builder.cleanAllProjects() : builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user