mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-20 01:54:20 -06:00
Make SolutionBuilder handle BuilderProgram in preparation to handle incremental builds
This commit is contained in:
parent
9fcfa28c40
commit
5d6ecb5436
@ -1391,6 +1391,14 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function copyProperities<T1 extends T2, T2>(first: T1, second: T2) {
|
||||
for (const id in second) {
|
||||
if (hasOwnProperty.call(second, id)) {
|
||||
(first as any)[id] = second[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface MultiMap<T> extends Map<T[]> {
|
||||
/**
|
||||
* Adds the value to an array of values associated with the key, and returns the array.
|
||||
|
||||
@ -69,6 +69,7 @@ namespace ts {
|
||||
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
|
||||
return createCompilerHostWorker(options, setParentNodes);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
// TODO(shkamat): update this after reworking ts build API
|
||||
export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
|
||||
@ -93,7 +94,6 @@ namespace ts {
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
|
||||
}
|
||||
|
||||
@ -203,18 +203,25 @@ namespace ts {
|
||||
return compilerHost;
|
||||
}
|
||||
|
||||
interface ComplierHostLikeForCache {
|
||||
fileExists(fileName: string): boolean;
|
||||
readFile(fileName: string, encoding?: string): string | undefined;
|
||||
directoryExists?(directory: string): boolean;
|
||||
createDirectory?(directory: string): void;
|
||||
writeFile?: WriteFileCallback;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function changeCompilerHostToUseCache(
|
||||
host: CompilerHost,
|
||||
export function changeCompilerHostLikeToUseCache(
|
||||
host: ComplierHostLikeForCache,
|
||||
toPath: (fileName: string) => Path,
|
||||
useCacheForSourceFile: boolean
|
||||
getSourceFile?: CompilerHost["getSourceFile"]
|
||||
) {
|
||||
const originalReadFile = host.readFile;
|
||||
const originalFileExists = host.fileExists;
|
||||
const originalDirectoryExists = host.directoryExists;
|
||||
const originalCreateDirectory = host.createDirectory;
|
||||
const originalWriteFile = host.writeFile;
|
||||
const originalGetSourceFile = host.getSourceFile;
|
||||
const readFileCache = createMap<string | false>();
|
||||
const fileExistsCache = createMap<boolean>();
|
||||
const directoryExistsCache = createMap<boolean>();
|
||||
@ -242,19 +249,17 @@ namespace ts {
|
||||
return setReadFileCache(key, fileName);
|
||||
};
|
||||
|
||||
if (useCacheForSourceFile) {
|
||||
host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
||||
const key = toPath(fileName);
|
||||
const value = sourceFileCache.get(key);
|
||||
if (value) return value;
|
||||
const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
||||
const key = toPath(fileName);
|
||||
const value = sourceFileCache.get(key);
|
||||
if (value) return value;
|
||||
|
||||
const sourceFile = originalGetSourceFile.call(host, fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) {
|
||||
sourceFileCache.set(key, sourceFile);
|
||||
}
|
||||
return sourceFile;
|
||||
};
|
||||
}
|
||||
const sourceFile = getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
||||
if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) {
|
||||
sourceFileCache.set(key, sourceFile);
|
||||
}
|
||||
return sourceFile;
|
||||
} : undefined;
|
||||
|
||||
// fileExists for any kind of extension
|
||||
host.fileExists = fileName => {
|
||||
@ -265,23 +270,25 @@ namespace ts {
|
||||
fileExistsCache.set(key, !!newValue);
|
||||
return newValue;
|
||||
};
|
||||
host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
|
||||
const key = toPath(fileName);
|
||||
fileExistsCache.delete(key);
|
||||
if (originalWriteFile) {
|
||||
host.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
|
||||
const key = toPath(fileName);
|
||||
fileExistsCache.delete(key);
|
||||
|
||||
const value = readFileCache.get(key);
|
||||
if (value && value !== data) {
|
||||
readFileCache.delete(key);
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
else if (useCacheForSourceFile) {
|
||||
const sourceFile = sourceFileCache.get(key);
|
||||
if (sourceFile && sourceFile.text !== data) {
|
||||
const value = readFileCache.get(key);
|
||||
if (value && value !== data) {
|
||||
readFileCache.delete(key);
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
}
|
||||
originalWriteFile.call(host, fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
};
|
||||
else if (getSourceFileWithCache) {
|
||||
const sourceFile = sourceFileCache.get(key);
|
||||
if (sourceFile && sourceFile.text !== data) {
|
||||
sourceFileCache.delete(key);
|
||||
}
|
||||
}
|
||||
originalWriteFile.call(host, fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
};
|
||||
}
|
||||
|
||||
// directoryExists
|
||||
if (originalDirectoryExists && originalCreateDirectory) {
|
||||
@ -306,7 +313,7 @@ namespace ts {
|
||||
originalDirectoryExists,
|
||||
originalCreateDirectory,
|
||||
originalWriteFile,
|
||||
originalGetSourceFile,
|
||||
getSourceFileWithCache,
|
||||
readFileWithCache
|
||||
};
|
||||
}
|
||||
@ -735,7 +742,7 @@ namespace ts {
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
const host = createProgramOptions.host || createCompilerHost(options);
|
||||
const configParsingHost = parseConfigHostFromCompilerHost(host);
|
||||
const configParsingHost = parseConfigHostFromCompilerHostLike(host);
|
||||
|
||||
let skipDefaultLib = options.noLib;
|
||||
const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options));
|
||||
@ -3104,18 +3111,28 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
interface CompilerHostLike {
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getCurrentDirectory(): string;
|
||||
fileExists(fileName: string): boolean;
|
||||
readFile(fileName: string): string | undefined;
|
||||
readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
|
||||
trace?(s: string): void;
|
||||
onUnRecoverableConfigFileDiagnostic?: DiagnosticReporter;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost {
|
||||
export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, directoryStructureHost: DirectoryStructureHost = host): ParseConfigFileHost {
|
||||
return {
|
||||
fileExists: f => host.fileExists(f),
|
||||
readDirectory(root, extensions, excludes, includes, depth) {
|
||||
Debug.assertDefined(host.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return host.readDirectory!(root, extensions, excludes, includes, depth);
|
||||
Debug.assertDefined(directoryStructureHost.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'");
|
||||
return directoryStructureHost.readDirectory!(root, extensions, excludes, includes, depth);
|
||||
},
|
||||
readFile: f => host.readFile(f),
|
||||
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
|
||||
getCurrentDirectory: () => host.getCurrentDirectory(),
|
||||
onUnRecoverableConfigFileDiagnostic: () => undefined,
|
||||
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic || (() => undefined),
|
||||
trace: host.trace ? (s) => host.trace!(s) : undefined
|
||||
};
|
||||
}
|
||||
|
||||
@ -321,7 +321,7 @@ namespace ts {
|
||||
return fileExtensionIs(fileName, Extension.Dts);
|
||||
}
|
||||
|
||||
export interface SolutionBuilderHostBase extends CompilerHost {
|
||||
export interface SolutionBuilderHostBase<T extends BuilderProgram> extends ProgramHost<T> {
|
||||
getModifiedTime(fileName: string): Date | undefined;
|
||||
setModifiedTime(fileName: string, date: Date): void;
|
||||
deleteFile(fileName: string): void;
|
||||
@ -331,15 +331,14 @@ namespace ts {
|
||||
|
||||
// TODO: To do better with watch mode and normal build mode api that creates program and emits files
|
||||
// This currently helps enable --diagnostics and --extendedDiagnostics
|
||||
beforeCreateProgram?(options: CompilerOptions): void;
|
||||
afterProgramEmitAndDiagnostics?(program: Program): void;
|
||||
}
|
||||
|
||||
export interface SolutionBuilderHost extends SolutionBuilderHostBase {
|
||||
export interface SolutionBuilderHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T> {
|
||||
reportErrorSummary?: ReportEmitErrorSummary;
|
||||
}
|
||||
|
||||
export interface SolutionBuilderWithWatchHost extends SolutionBuilderHostBase, WatchHost {
|
||||
export interface SolutionBuilderWithWatchHost<T extends BuilderProgram> extends SolutionBuilderHostBase<T>, WatchHost {
|
||||
}
|
||||
|
||||
export interface SolutionBuilder {
|
||||
@ -372,30 +371,29 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createSolutionBuilderHostBase(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
|
||||
const host = createCompilerHostWorker({}, /*setParentNodes*/ undefined, system) as SolutionBuilderHostBase;
|
||||
function createSolutionBuilderHostBase<T extends BuilderProgram>(system: System, createProgram: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter) {
|
||||
const host = createProgramHost(system, createProgram) as SolutionBuilderHostBase<T>;
|
||||
host.getModifiedTime = system.getModifiedTime ? path => system.getModifiedTime!(path) : () => undefined;
|
||||
host.setModifiedTime = system.setModifiedTime ? (path, date) => system.setModifiedTime!(path, date) : noop;
|
||||
host.deleteFile = system.deleteFile ? path => system.deleteFile!(path) : noop;
|
||||
host.reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system);
|
||||
host.reportSolutionBuilderStatus = reportSolutionBuilderStatus || createBuilderStatusReporter(system);
|
||||
return host;
|
||||
|
||||
// TODO after program create
|
||||
}
|
||||
|
||||
export function createSolutionBuilderHost(system = sys, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) {
|
||||
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost;
|
||||
export function createSolutionBuilderHost<T extends BuilderProgram = BuilderProgram>(system = sys, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportErrorSummary?: ReportEmitErrorSummary) {
|
||||
const host = createSolutionBuilderHostBase(system, createProgram || createAbstractBuilder as any as CreateProgram<T>, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderHost<T>;
|
||||
host.reportErrorSummary = reportErrorSummary;
|
||||
return host;
|
||||
}
|
||||
|
||||
export function createSolutionBuilderWithWatchHost(system?: System, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
|
||||
const host = createSolutionBuilderHostBase(system, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost;
|
||||
// TODO: we should use emit and semantic diagnostics builder but that needs to handle errors little differently so handle it later
|
||||
export function createSolutionBuilderWithWatchHost<T extends BuilderProgram = SemanticDiagnosticsBuilderProgram>(system = sys, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportSolutionBuilderStatus?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter) {
|
||||
const host = createSolutionBuilderHostBase(system, createProgram || createSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>, reportDiagnostic, reportSolutionBuilderStatus) as SolutionBuilderWithWatchHost<T>;
|
||||
const watchHost = createWatchHost(system, reportWatchStatus);
|
||||
host.onWatchStatusChange = watchHost.onWatchStatusChange;
|
||||
host.watchFile = watchHost.watchFile;
|
||||
host.watchDirectory = watchHost.watchDirectory;
|
||||
host.setTimeout = watchHost.setTimeout;
|
||||
host.clearTimeout = watchHost.clearTimeout;
|
||||
copyProperities(host, watchHost);
|
||||
return host;
|
||||
}
|
||||
|
||||
@ -413,13 +411,13 @@ namespace ts {
|
||||
* TODO: use SolutionBuilderWithWatchHost => watchedSolution
|
||||
* use SolutionBuilderHost => Solution
|
||||
*/
|
||||
export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder;
|
||||
export function createSolutionBuilder(host: SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch;
|
||||
export function createSolutionBuilder(host: SolutionBuilderHost | SolutionBuilderWithWatchHost, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch {
|
||||
const hostWithWatch = host as SolutionBuilderWithWatchHost;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilder;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderWithWatchHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch;
|
||||
export function createSolutionBuilder<T extends BuilderProgram>(host: SolutionBuilderHost<T> | SolutionBuilderWithWatchHost<T>, rootNames: ReadonlyArray<string>, defaultOptions: BuildOptions): SolutionBuilderWithWatch {
|
||||
const hostWithWatch = host as SolutionBuilderWithWatchHost<T>;
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHost(host);
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host);
|
||||
|
||||
// State of the solution
|
||||
let options = defaultOptions;
|
||||
@ -434,6 +432,8 @@ namespace ts {
|
||||
let globalDependencyGraph: DependencyGraph | undefined;
|
||||
const writeFileName = (s: string) => host.trace && host.trace(s);
|
||||
let readFileWithCache = (f: string) => host.readFile(f);
|
||||
let projectCompilerOptions = baseCompilerOptions;
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => projectCompilerOptions);
|
||||
|
||||
// Watch state
|
||||
const diagnostics = createFileMap<ReadonlyArray<Diagnostic>>(toPath);
|
||||
@ -919,7 +919,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportErrorSummary() {
|
||||
if (options.watch || (host as SolutionBuilderHost).reportErrorSummary) {
|
||||
if (options.watch || (host as SolutionBuilderHost<T>).reportErrorSummary) {
|
||||
// Report errors from the other projects
|
||||
getGlobalDependencyGraph().buildQueue.forEach(project => {
|
||||
if (!projectErrorsReported.hasKey(project)) {
|
||||
@ -932,7 +932,7 @@ namespace ts {
|
||||
reportWatchStatus(getWatchErrorSummaryDiagnosticMessage(totalErrors), totalErrors);
|
||||
}
|
||||
else {
|
||||
(host as SolutionBuilderHost).reportErrorSummary!(totalErrors);
|
||||
(host as SolutionBuilderHost<T>).reportErrorSummary!(totalErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1051,17 +1051,17 @@ namespace ts {
|
||||
return BuildResultFlags.None;
|
||||
}
|
||||
|
||||
const programOptions: CreateProgramOptions = {
|
||||
projectReferences: configFile.projectReferences,
|
||||
host,
|
||||
rootNames: configFile.fileNames,
|
||||
options: configFile.options,
|
||||
configFileParsingDiagnostics: configFile.errors
|
||||
};
|
||||
if (host.beforeCreateProgram) {
|
||||
host.beforeCreateProgram(options);
|
||||
}
|
||||
const program = createProgram(programOptions);
|
||||
// TODO: handle resolve module name to cache result in project reference redirect
|
||||
projectCompilerOptions = configFile.options;
|
||||
const program = host.createProgram(
|
||||
configFile.fileNames,
|
||||
configFile.options,
|
||||
compilerHost,
|
||||
/*oldProgram*/ undefined,
|
||||
configFile.errors,
|
||||
configFile.projectReferences
|
||||
);
|
||||
projectCompilerOptions = baseCompilerOptions;
|
||||
|
||||
// Don't emit anything in the presence of syntactic errors or options diagnostics
|
||||
const syntaxDiagnostics = [
|
||||
@ -1105,7 +1105,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
writeFile(host, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
|
||||
if (priorChangeTime !== undefined) {
|
||||
newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime);
|
||||
unchangedOutputs.setValue(name, priorChangeTime);
|
||||
@ -1209,12 +1209,15 @@ namespace ts {
|
||||
if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); }
|
||||
// TODO:: In watch mode as well to use caches for incremental build once we can invalidate caches correctly and have right api
|
||||
// Override readFile for json files and output .d.ts to cache the text
|
||||
const { originalReadFile, originalFileExists, originalDirectoryExists,
|
||||
originalCreateDirectory, originalWriteFile, originalGetSourceFile,
|
||||
readFileWithCache: newReadFileWithCache
|
||||
} = changeCompilerHostToUseCache(host, toPath, /*useCacheForSourceFile*/ true);
|
||||
const savedReadFileWithCache = readFileWithCache;
|
||||
const savedGetSourceFile = compilerHost.getSourceFile;
|
||||
|
||||
const { originalReadFile, originalFileExists, originalDirectoryExists,
|
||||
originalCreateDirectory, originalWriteFile, getSourceFileWithCache,
|
||||
readFileWithCache: newReadFileWithCache
|
||||
} = changeCompilerHostLikeToUseCache(host, toPath, (...args) => savedGetSourceFile.call(compilerHost, ...args));
|
||||
readFileWithCache = newReadFileWithCache;
|
||||
compilerHost.getSourceFile = getSourceFileWithCache!;
|
||||
|
||||
const graph = getGlobalDependencyGraph();
|
||||
reportBuildQueue(graph);
|
||||
@ -1271,8 +1274,8 @@ namespace ts {
|
||||
host.directoryExists = originalDirectoryExists;
|
||||
host.createDirectory = originalCreateDirectory;
|
||||
host.writeFile = originalWriteFile;
|
||||
compilerHost.getSourceFile = savedGetSourceFile;
|
||||
readFileWithCache = savedReadFileWithCache;
|
||||
host.getSourceFile = originalGetSourceFile;
|
||||
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
|
||||
}
|
||||
|
||||
@ -1300,7 +1303,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function relName(path: string): string {
|
||||
return convertToRelativePath(path, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
|
||||
return convertToRelativePath(path, host.getCurrentDirectory(), f => compilerHost.getCanonicalFileName(f));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2827,7 +2827,7 @@ namespace ts {
|
||||
fileName: string,
|
||||
data: string,
|
||||
writeByteOrderMark: boolean,
|
||||
onError: ((message: string) => void) | undefined,
|
||||
onError?: (message: string) => void,
|
||||
sourceFiles?: ReadonlyArray<SourceFile>,
|
||||
) => void;
|
||||
|
||||
|
||||
@ -203,23 +203,81 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCompilerOptions: () => CompilerOptions, directoryStructureHost: DirectoryStructureHost = host): CompilerHost {
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
return {
|
||||
getSourceFile: (fileName, languageVersion, onError) => {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
performance.mark("beforeIORead");
|
||||
text = host.readFile(fileName, getCompilerOptions().charset);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation!()),
|
||||
getDefaultLibFileName: options => host.getDefaultLibFileName(options),
|
||||
writeFile,
|
||||
getCurrentDirectory: memoize(() => host.getCurrentDirectory()),
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getCanonicalFileName: createGetCanonicalFileName(useCaseSensitiveFileNames),
|
||||
getNewLine: memoize(() => getNewLineCharacter(getCompilerOptions(), () => host.getNewLine())),
|
||||
fileExists: f => host.fileExists(f),
|
||||
readFile: f => host.readFile(f),
|
||||
trace: host.trace && (s => host.trace!(s)),
|
||||
directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists!(path)),
|
||||
getDirectories: (directoryStructureHost.getDirectories && ((path: string) => directoryStructureHost.getDirectories!(path)))!, // TODO: GH#18217
|
||||
realpath: host.realpath && (s => host.realpath!(s)),
|
||||
getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable!(name)) : (() => ""),
|
||||
createHash: host.createHash && (data => host.createHash!(data)),
|
||||
readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
};
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
|
||||
const parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
if (host.createDirectory) host.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
||||
try {
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
host.writeFile!(fileName, text, writeByteOrderMark);
|
||||
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch compiler host that can be extended with config file or root file names and options host
|
||||
*/
|
||||
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram: CreateProgram<T> | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
|
||||
if (!createProgram) {
|
||||
createProgram = createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
|
||||
}
|
||||
|
||||
export function createProgramHost<T extends BuilderProgram>(system: System, createProgram: CreateProgram<T>): ProgramHost<T> {
|
||||
const getDefaultLibLocation = memoize(() => getDirectoryPath(normalizePath(system.getExecutingFilePath())));
|
||||
let host: DirectoryStructureHost = system;
|
||||
host; // tslint:disable-line no-unused-expression (TODO: `host` is unused!)
|
||||
const useCaseSensitiveFileNames = () => system.useCaseSensitiveFileNames;
|
||||
const writeFileName = (s: string) => system.write(s + system.newLine);
|
||||
const { onWatchStatusChange, watchFile, watchDirectory, setTimeout, clearTimeout } = createWatchHost(system, reportWatchStatus);
|
||||
return {
|
||||
useCaseSensitiveFileNames,
|
||||
useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames,
|
||||
getNewLine: () => system.newLine,
|
||||
getCurrentDirectory: () => system.getCurrentDirectory(),
|
||||
getCurrentDirectory: memoize(() => system.getCurrentDirectory()),
|
||||
getDefaultLibLocation,
|
||||
getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)),
|
||||
fileExists: path => system.fileExists(path),
|
||||
@ -229,25 +287,23 @@ namespace ts {
|
||||
readDirectory: (path, extensions, exclude, include, depth) => system.readDirectory(path, extensions, exclude, include, depth),
|
||||
realpath: system.realpath && (path => system.realpath!(path)),
|
||||
getEnvironmentVariable: system.getEnvironmentVariable && (name => system.getEnvironmentVariable(name)),
|
||||
watchFile,
|
||||
watchDirectory,
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
trace: s => system.write(s + system.newLine),
|
||||
onWatchStatusChange,
|
||||
createDirectory: path => system.createDirectory(path),
|
||||
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
|
||||
onCachedDirectoryStructureHostCreate: cacheHost => host = cacheHost || system,
|
||||
createHash: system.createHash && (s => system.createHash!(s)),
|
||||
createProgram,
|
||||
afterProgramCreate: emitFilesAndReportErrorUsingBuilder
|
||||
createProgram
|
||||
};
|
||||
}
|
||||
|
||||
function getDefaultLibLocation() {
|
||||
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
|
||||
}
|
||||
|
||||
function emitFilesAndReportErrorUsingBuilder(builderProgram: BuilderProgram) {
|
||||
/**
|
||||
* Creates the watch compiler host that can be extended with config file or root file names and options host
|
||||
*/
|
||||
function createWatchCompilerHost<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(system = sys, createProgram: CreateProgram<T> | undefined, reportDiagnostic: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHost<T> {
|
||||
const writeFileName = (s: string) => system.write(s + system.newLine);
|
||||
const result = createProgramHost(system, createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>) as WatchCompilerHost<T>;
|
||||
copyProperities(result, createWatchHost(system, reportWatchStatus));
|
||||
result.afterProgramCreate = builderProgram => {
|
||||
const compilerOptions = builderProgram.getCompilerOptions();
|
||||
const newLine = getNewLineCharacter(compilerOptions, () => system.newLine);
|
||||
|
||||
@ -255,13 +311,14 @@ namespace ts {
|
||||
builderProgram,
|
||||
reportDiagnostic,
|
||||
writeFileName,
|
||||
errorCount => onWatchStatusChange!(
|
||||
errorCount => result.onWatchStatusChange!(
|
||||
createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(errorCount), errorCount),
|
||||
newLine,
|
||||
compilerOptions
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -300,6 +357,7 @@ namespace ts {
|
||||
export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
|
||||
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
|
||||
export type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>, projectReferences?: ReadonlyArray<ProjectReference> | undefined) => T;
|
||||
|
||||
/** Host that has watch functionality used in --watch mode */
|
||||
export interface WatchHost {
|
||||
/** If provided, called with Diagnostic message that informs about change in watch status */
|
||||
@ -314,19 +372,11 @@ namespace ts {
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
|
||||
// Sub set of compiler host methods to read and generate new program
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
@ -366,16 +416,25 @@ namespace ts {
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
|
||||
/** Internal interface used to wire emit through same host */
|
||||
|
||||
/*@internal*/
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> {
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
createDirectory?(path: string): void;
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void;
|
||||
}
|
||||
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
@ -488,8 +547,6 @@ namespace ts {
|
||||
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCurrentDirectory = () => currentDirectory;
|
||||
const readFile: (path: string, encoding?: string) => string | undefined = (path, encoding) => host.readFile(path, encoding);
|
||||
const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host;
|
||||
let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host;
|
||||
let configFileSpecs: ConfigFileSpecs;
|
||||
@ -502,15 +559,7 @@ namespace ts {
|
||||
host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost);
|
||||
}
|
||||
const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host;
|
||||
const parseConfigFileHost: ParseConfigFileHost = {
|
||||
useCaseSensitiveFileNames,
|
||||
readDirectory: (path, extensions, exclude, include, depth) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
fileExists: path => host.fileExists(path),
|
||||
readFile,
|
||||
getCurrentDirectory,
|
||||
onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic,
|
||||
trace: host.trace ? s => host.trace!(s) : undefined
|
||||
};
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host, directoryStructureHost);
|
||||
|
||||
// From tsc we want to get already parsed result and hence check for rootFileNames
|
||||
let newLine = updateNewLine();
|
||||
@ -534,42 +583,29 @@ namespace ts {
|
||||
watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, WatchType.ConfigFile);
|
||||
}
|
||||
|
||||
const compilerHost: CompilerHost & ResolutionCacheHost = {
|
||||
// Members for CompilerHost
|
||||
getSourceFile: (fileName, languageVersion, onError?, shouldCreateNewSourceFile?) => getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile),
|
||||
getSourceFileByPath: getVersionedSourceFileByPath,
|
||||
getDefaultLibLocation: host.getDefaultLibLocation && (() => host.getDefaultLibLocation!()),
|
||||
getDefaultLibFileName: options => host.getDefaultLibFileName(options),
|
||||
writeFile,
|
||||
getCurrentDirectory,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getCanonicalFileName,
|
||||
getNewLine: () => newLine,
|
||||
fileExists,
|
||||
readFile,
|
||||
trace: host.trace && (s => host.trace!(s)),
|
||||
directoryExists: directoryStructureHost.directoryExists && (path => directoryStructureHost.directoryExists!(path)),
|
||||
getDirectories: (directoryStructureHost.getDirectories && ((path: string) => directoryStructureHost.getDirectories!(path)))!, // TODO: GH#18217
|
||||
realpath: host.realpath && (s => host.realpath!(s)),
|
||||
getEnvironmentVariable: host.getEnvironmentVariable ? (name => host.getEnvironmentVariable!(name)) : (() => ""),
|
||||
onReleaseOldSourceFile,
|
||||
createHash: host.createHash && (data => host.createHash!(data)),
|
||||
// Members for ResolutionCacheHost
|
||||
toPath,
|
||||
getCompilationSettings: () => compilerOptions,
|
||||
watchDirectoryOfFailedLookupLocation: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.FailedLookupLocations),
|
||||
watchTypeRootsDirectory: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.TypeRoots),
|
||||
getCachedDirectoryStructureHost: () => cachedDirectoryStructureHost,
|
||||
onInvalidatedResolution: scheduleProgramUpdate,
|
||||
onChangedAutomaticTypeDirectiveNames: () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
},
|
||||
maxNumberOfFilesToIterateForInvalidation: host.maxNumberOfFilesToIterateForInvalidation,
|
||||
getCurrentProgram,
|
||||
writeLog,
|
||||
readDirectory: (path, extensions, exclude, include, depth?) => directoryStructureHost.readDirectory!(path, extensions, exclude, include, depth),
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
|
||||
// Members for CompilerHost
|
||||
const getNewSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
|
||||
compilerHost.getSourceFileByPath = getVersionedSourceFileByPath;
|
||||
compilerHost.getNewLine = () => newLine;
|
||||
compilerHost.fileExists = fileExists;
|
||||
compilerHost.onReleaseOldSourceFile = onReleaseOldSourceFile;
|
||||
// Members for ResolutionCacheHost
|
||||
compilerHost.toPath = toPath;
|
||||
compilerHost.getCompilationSettings = () => compilerOptions;
|
||||
compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.FailedLookupLocations);
|
||||
compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.TypeRoots);
|
||||
compilerHost.getCachedDirectoryStructureHost = () => cachedDirectoryStructureHost;
|
||||
compilerHost.onInvalidatedResolution = scheduleProgramUpdate;
|
||||
compilerHost.onChangedAutomaticTypeDirectiveNames = () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
};
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = host.maxNumberOfFilesToIterateForInvalidation;
|
||||
compilerHost.getCurrentProgram = getCurrentProgram;
|
||||
compilerHost.writeLog = writeLog;
|
||||
|
||||
// Cache for the module resolution
|
||||
const resolutionCache = createResolutionCache(compilerHost, configFileName ?
|
||||
getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) :
|
||||
@ -712,7 +748,7 @@ namespace ts {
|
||||
|
||||
// Create new source file if requested or the versions dont match
|
||||
if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) {
|
||||
const sourceFile = getNewSourceFile();
|
||||
const sourceFile = getNewSourceFile.call(compilerHost, fileName, languageVersion, onError);
|
||||
if (hostSourceFile) {
|
||||
if (shouldCreateNewSourceFile) {
|
||||
hostSourceFile.version++;
|
||||
@ -747,23 +783,6 @@ namespace ts {
|
||||
return sourceFile;
|
||||
}
|
||||
return hostSourceFile.sourceFile;
|
||||
|
||||
function getNewSourceFile() {
|
||||
let text: string | undefined;
|
||||
try {
|
||||
performance.mark("beforeIORead");
|
||||
text = host.readFile(fileName, compilerOptions.charset);
|
||||
performance.mark("afterIORead");
|
||||
performance.measure("I/O Read", "beforeIORead", "afterIORead");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function nextSourceFileVersion(path: Path) {
|
||||
@ -978,30 +997,5 @@ namespace ts {
|
||||
WatchType.WildcardDirectory
|
||||
);
|
||||
}
|
||||
|
||||
function ensureDirectoriesExist(directoryPath: string) {
|
||||
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
|
||||
const parentDirectory = getDirectoryPath(directoryPath);
|
||||
ensureDirectoriesExist(parentDirectory);
|
||||
host.createDirectory!(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
||||
try {
|
||||
performance.mark("beforeIOWrite");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
host.writeFile!(fileName, text, writeByteOrderMark);
|
||||
|
||||
performance.mark("afterIOWrite");
|
||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +375,9 @@ namespace fakes {
|
||||
}
|
||||
}
|
||||
|
||||
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost {
|
||||
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost<ts.BuilderProgram> {
|
||||
createProgram = ts.createAbstractBuilder;
|
||||
|
||||
diagnostics: ts.Diagnostic[] = [];
|
||||
|
||||
reportDiagnostic(diagnostic: ts.Diagnostic) {
|
||||
|
||||
@ -85,7 +85,7 @@ namespace ts {
|
||||
|
||||
// We shouldn't have any errors about invalid tsconfig files in these tests
|
||||
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
|
||||
const file = parseJsonConfigFileContent(config, parseConfigHostFromCompilerHost(host), getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName);
|
||||
const file = parseJsonConfigFileContent(config, parseConfigHostFromCompilerHostLike(host), getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName);
|
||||
file.options.configFilePath = entryPointConfigFileName;
|
||||
const prog = createProgram({
|
||||
rootNames: file.fileNames,
|
||||
|
||||
@ -265,7 +265,7 @@ export class cNew {}`);
|
||||
// Build downstream projects should update 'tests', but not 'core'
|
||||
tick();
|
||||
builder.buildInvalidatedProject();
|
||||
assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt");
|
||||
assert.equal(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt");
|
||||
assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt");
|
||||
});
|
||||
});
|
||||
|
||||
@ -206,9 +206,9 @@ namespace ts {
|
||||
|
||||
// TODO: change this to host if watch => watchHost otherwiue without watch
|
||||
const buildHost = buildOptions.watch ?
|
||||
createSolutionBuilderWithWatchHost(sys, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()) :
|
||||
createSolutionBuilderHost(sys, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createReportErrorSummary(buildOptions));
|
||||
buildHost.beforeCreateProgram = enableStatistics;
|
||||
createSolutionBuilderWithWatchHost(sys, createSemanticDiagnosticsBuilderProgram, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()) :
|
||||
createSolutionBuilderHost(sys, createAbstractBuilder, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createReportErrorSummary(buildOptions));
|
||||
updateCreateProgram(buildHost);
|
||||
buildHost.afterProgramEmitAndDiagnostics = reportStatistics;
|
||||
|
||||
const builder = createSolutionBuilder(buildHost, projects, buildOptions);
|
||||
@ -234,7 +234,7 @@ namespace ts {
|
||||
const host = createCompilerHost(options);
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
|
||||
changeCompilerHostToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName), /*useCacheForSourceFile*/ false);
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
enableStatistics(options);
|
||||
|
||||
const programOptions: CreateProgramOptions = {
|
||||
@ -255,15 +255,19 @@ namespace ts {
|
||||
return sys.exit(exitStatus);
|
||||
}
|
||||
|
||||
function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
|
||||
const compileUsingBuilder = watchCompilerHost.createProgram;
|
||||
watchCompilerHost.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
||||
function updateCreateProgram<T extends BuilderProgram>(host: { createProgram: CreateProgram<T>; }) {
|
||||
const compileUsingBuilder = host.createProgram;
|
||||
host.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
|
||||
Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram));
|
||||
if (options !== undefined) {
|
||||
enableStatistics(options);
|
||||
}
|
||||
return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
};
|
||||
}
|
||||
|
||||
function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
|
||||
updateCreateProgram(watchCompilerHost);
|
||||
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217
|
||||
watchCompilerHost.afterProgramCreate = builderProgram => {
|
||||
emitFilesUsingBuilder(builderProgram);
|
||||
|
||||
@ -1778,7 +1778,7 @@ declare namespace ts {
|
||||
type ResolvedConfigFileName = string & {
|
||||
_isResolvedConfigFileName: never;
|
||||
};
|
||||
type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles?: ReadonlyArray<SourceFile>) => void;
|
||||
type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>) => void;
|
||||
class OperationCanceledException {
|
||||
}
|
||||
interface CancellationToken {
|
||||
@ -4333,13 +4333,11 @@ declare namespace ts {
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
|
||||
interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getNewLine(): string;
|
||||
getCurrentDirectory(): string;
|
||||
@ -4373,6 +4371,10 @@ declare namespace ts {
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
}
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
|
||||
10
tests/baselines/reference/api/typescript.d.ts
vendored
10
tests/baselines/reference/api/typescript.d.ts
vendored
@ -1778,7 +1778,7 @@ declare namespace ts {
|
||||
type ResolvedConfigFileName = string & {
|
||||
_isResolvedConfigFileName: never;
|
||||
};
|
||||
type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError: ((message: string) => void) | undefined, sourceFiles?: ReadonlyArray<SourceFile>) => void;
|
||||
type WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: ReadonlyArray<SourceFile>) => void;
|
||||
class OperationCanceledException {
|
||||
}
|
||||
interface CancellationToken {
|
||||
@ -4333,13 +4333,11 @@ declare namespace ts {
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
interface WatchCompilerHost<T extends BuilderProgram> extends WatchHost {
|
||||
interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getNewLine(): string;
|
||||
getCurrentDirectory(): string;
|
||||
@ -4373,6 +4371,10 @@ declare namespace ts {
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
}
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user