import { createError } from '@cirrusct/error'; import * as nodePath from 'path'; import * as ts from 'typescript'; import { createParsedConfig, createProgram, formatDiagnostics } from './lib'; import { ProgramOptions, TsConfig, TsProjectOptions } from './types'; const tsBuildInfoFile = './.tsbuildinfo'; const DefaultIncrementalBuild = true; export class TsProject { private _parsedConfig: ts.ParsedCommandLine; private _compilerHost: ts.CompilerHost; private _builderProgram: ts.BuilderProgram; private _lastEmitResult: ts.EmitResult; constructor(public readonly projectOptions: TsProjectOptions) {} public get tsVersion(): string { return ts.version; } public get parsedConfig(): ts.ParsedCommandLine { if (!this._parsedConfig) { this._parsedConfig = createParsedConfig(this.projectOptions); } return this._parsedConfig; } // public get compilerHost(): ts.CompilerHost { // if (!this._compilerHost) { // this._compilerHost = ts.createCompilerHost(this.parsedConfig.options, true); // } // return this._compilerHost; // } public get compilerHost(): ts.CompilerHost { if (!this._compilerHost) { this._compilerHost = ts.createIncrementalCompilerHost(this.parsedConfig.options); } return this._compilerHost; } public get builderProgram(): ts.BuilderProgram { if (!this._builderProgram) { const buildInfoFilePath = nodePath.join(this.parsedConfig.options.outDir, tsBuildInfoFile); this._builderProgram = ts.createIncrementalProgram({ rootNames: this.projectOptions.fileNames || this.parsedConfig.fileNames, host: this.compilerHost, options: { ...(this.projectOptions.parsedCompilerOptions || this.parsedConfig.options), incremental: this.projectOptions.incremental === false ? false : DefaultIncrementalBuild, tsBuildInfoFile: buildInfoFilePath, }, }); // this._program = ts.createProgram( // this.projectOptions.fileNames || this.parsedConfig.fileNames, // this.projectOptions.parsedCompilerOptions || this.parsedConfig.options, // this.compilerHost // ); } return this._builderProgram; } public get program(): ts.Program { return this.builderProgram.getProgram(); } public emit = (): ts.EmitResult => { this._lastEmitResult = this.program.emit(); return this._lastEmitResult; }; public getDiagnostics = (): ts.Diagnostic[] => { return ts .getPreEmitDiagnostics(this.program) .concat(this._lastEmitResult ? (this._lastEmitResult.diagnostics as any) : []); // tslint:disable-line: no-any }; public getFormattedDiagnostics = (useColorAndContext: boolean = true): string => { return formatDiagnostics(this.getDiagnostics(), useColorAndContext); }; }