Skip to content

Commit 4f5cab8

Browse files
committed
Add sample for SolutionBuilder API
1 parent d3be118 commit 4f5cab8

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

Using-the-Compiler-API.md

+141
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,147 @@ function incrementalCompile(): void {
357357
incrementalCompile();
358358
```
359359

360+
## A minimal solution compiler
361+
362+
To compile solution that is project and its dependencies the way `tsc --b` does, we need to create a `SolutionBuilder` which iterates through projects to build. This can be achieved by using `createSolutionBuilder` which takes host which is `SolutionBuilderHost` and can be created using `createSolutionBuilderHost`, root solutions to build and buildOptions. To create a solution builder that also watches for changes (similar to `tsc --b --w`), you can use `createSolutionBuilderWithWatch` and host using `createSolutionBuilderWithWatchHost`.
363+
364+
```TypeScript
365+
import * as ts from "typescript";
366+
367+
/**
368+
* To compile solution similar to tsc --b
369+
*/
370+
function compileSolution(rootNames: string, options: ts.BuildOptions): void {
371+
const host = ts.createSolutionBuilderHost(
372+
// System like host, default is ts.sys
373+
/*system*/ undefined,
374+
// createProgram can be passed in here to choose strategy for incremental compiler just like when creating incremental watcher program.
375+
// Default is ts.createSemanticDiagnosticsBuilderProgram
376+
/*createProgram*/ undefined,
377+
reportDiagnostic,
378+
reportSolutionBuilderStatus,
379+
reportErrorSummary
380+
);
381+
382+
const solution = ts.createSolutionBuilder(
383+
host,
384+
rootNames,
385+
options
386+
);
387+
388+
// Builds the solution
389+
const exitCode = solution.build();
390+
console.log(`Process exiting with code '${exitCode}'.`);
391+
process.exit(exitCode);
392+
393+
// // Alternative to build if you want to take custom action for each project,
394+
// while (true) {
395+
// const project = solution.getNextInvalidatedProject();
396+
// if (!project) { break; }
397+
//
398+
// // Do custom things on project here
399+
// console.log(`Working with ${project.project}`);
400+
//
401+
// // project.kind has info decides which type of project it is:
402+
// // ts.InvalidatedProjectKind.Build:: The project needs to be built (create program and emit the files)
403+
// // ts.InvalidatedProjectKind.UpdateBundle:: The project needs to combine outputs of references and its own files emit (using old output.js and .tsbuildinfo file) to get new output
404+
// // ts.InvalidatedProjectKind.UpdateOutputFileStamps:: The project needs to update timestamps of existing outputs since output is correct but output timestamp is older than one of its dependency
405+
//
406+
// // Finish working with this project to get next project
407+
// project.done();
408+
// }
409+
}
410+
411+
/**
412+
* To compile solution and watch changes similar to tsc --b --w
413+
*/
414+
function compileSolutionWithWatch(rootNames: string, options: ts.BuildOptions): void {
415+
const host = ts.createSolutionBuilderWithWatchHost(
416+
// System like host, default is ts.sys
417+
/*system*/ undefined,
418+
// createProgram can be passed in here to choose strategy for incremental compiler just like when creating incremental watcher program.
419+
// Default is ts.createSemanticDiagnosticsBuilderProgram
420+
/*createProgram*/ undefined,
421+
reportDiagnostic,
422+
reportSolutionBuilderStatus,
423+
reportWatchStatus
424+
);
425+
426+
const solution = ts.createSolutionBuilderWithWatch(
427+
host,
428+
rootNames,
429+
options
430+
);
431+
432+
// Builds the solution and watches for changes
433+
solution.clean();
434+
}
435+
436+
/**
437+
* To clean solution similar to tsc --b --clean
438+
*/
439+
function cleanSolution(rootNames: string): void {
440+
// Create host
441+
const host = ts.createSolutionBuilderHost();
442+
443+
// Create solution builder
444+
const solution = ts.createSolutionBuilder(
445+
host,
446+
rootNames,
447+
{}
448+
);
449+
450+
// Clean the solution removing outputs
451+
const exitCode = solution.clean();
452+
console.log(`Process exiting with code '${exitCode}'.`);
453+
process.exit(exitCode);
454+
}
455+
456+
// Reports error
457+
function reportDiagnostic(diagnostic: ts.Diagnostic) {
458+
console.error(getTextForDiagnostic(diagnostic));
459+
}
460+
461+
// Reports status like Project needs to be built because output file doesnot exist
462+
function reportSolutionBuilderStatus(diagnostic: ts.Diagnostic) {
463+
console.info(getTextForDiagnostic(diagnostic));
464+
}
465+
466+
// Reports summary with number of errors
467+
function reportErrorSummary(errorCount: number) {
468+
console.info(`${errorCount} found.`);
469+
}
470+
471+
// Report status of watch like Starting compilation, Compilation completed etc
472+
function reportWatchStatus(diagnostic: ts.Diagnostic) {
473+
console.info(getTextForDiagnostic(diagnostic));
474+
}
475+
476+
function getTextForDiagnostic(diagnostic: ts.Diagnostic): string {
477+
if (diagnostic.file) {
478+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
479+
diagnostic.start!
480+
);
481+
const message = ts.flattenDiagnosticMessageText(
482+
diagnostic.messageText,
483+
"\n"
484+
);
485+
return `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
486+
} else {
487+
return `${ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")}`;
488+
}
489+
}
490+
491+
// To compile solution similar to tsc --b
492+
compileSolution(process.argv.slice(2), { verbose: true });
493+
494+
// To compile solution and watch changes similar to tsc --b --w
495+
compileSolutionWithWatch(process.argv.slice(2), { verbose: true });
496+
497+
// To clean solution similar to tsc --b --clean
498+
cleanSolution(process.argv.slice(2));
499+
```
500+
360501
## Incremental build support using the language services
361502

362503
> Please refer to the [[Using the Language Service API]] page for more details.

0 commit comments

Comments
 (0)