Move the polling settings to sys instead of watch utilities

This commit is contained in:
Sheetal Nandi 2018-01-16 13:15:39 -08:00
parent 09caaa3775
commit fa8d4cba78
7 changed files with 144 additions and 124 deletions

View File

@ -32,10 +32,10 @@ namespace ts {
}
/* @internal */
export enum WatchPriority {
High,
Medium,
Low
export enum PollingInterval {
High = 2000,
Medium = 500,
Low = 250
}
function getPriorityValues(highPriorityValue: number): [number, number, number] {
@ -44,36 +44,47 @@ namespace ts {
return [highPriorityValue, mediumPriorityValue, lowPriorityValue];
}
const pollingIntervalsForPriority = getPriorityValues(250);
function pollingInterval(watchPriority: WatchPriority): number {
function pollingInterval(watchPriority: PollingInterval): number {
return pollingIntervalsForPriority[watchPriority];
}
const pollingIntervalsForPriority = getPriorityValues(250);
/* @internal */
export function watchFileUsingPriorityPollingInterval(host: System, fileName: string, callback: FileWatcherCallback, watchPriority: WatchPriority): FileWatcher {
export function watchFileUsingPriorityPollingInterval(host: System, fileName: string, callback: FileWatcherCallback, watchPriority: PollingInterval): FileWatcher {
return host.watchFile(fileName, callback, pollingInterval(watchPriority));
}
/* @internal */
export interface DynamicPriorityPollingStatsSet {
watchFile(fileName: string, callback: FileWatcherCallback, defaultPriority: WatchPriority): FileWatcher;
}
export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval) => FileWatcher;
/* @internal */
export const missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time
const chunkSizeOrUnchangedThresholdsForPriority = getPriorityValues(32);
function chunkSize(watchPriority: WatchPriority) {
return chunkSizeOrUnchangedThresholdsForPriority[watchPriority];
enum ChunkSize {
Low = 32,
Medium = 64,
High = 256
}
function chunkSize(pollingInterval: PollingInterval) {
switch (pollingInterval) {
case PollingInterval.Low:
return ChunkSize.Low;
case PollingInterval.Medium:
return ChunkSize.Medium;
case PollingInterval.High:
return ChunkSize.High;
}
}
/*@internal*/
export function unChangedThreshold(watchPriority: WatchPriority) {
return chunkSizeOrUnchangedThresholdsForPriority[watchPriority];
export function unChangedThreshold(pollingInterval: PollingInterval) {
return chunkSize(pollingInterval);
}
/* @internal */
export function createDynamicPriorityPollingStatsSet(host: System): DynamicPriorityPollingStatsSet {
export function createDynamicPriorityPollingWatchFile(host: System): HostWatchFile {
if (!host.getModifiedTime || !host.setTimeout) {
throw notImplemented();
}
@ -83,20 +94,20 @@ namespace ts {
unchangedPolls: number;
}
interface WatchPriorityQueue extends Array<WatchedFile> {
watchPriority: WatchPriority;
interface PollingIntervalQueue extends Array<WatchedFile> {
pollingInterval: PollingInterval;
pollIndex: number;
pollScheduled: boolean;
}
const watchedFiles: WatchedFile[] = [];
const changedFilesInLastPoll: WatchedFile[] = [];
const priorityQueues = [createPriorityQueue(WatchPriority.High), createPriorityQueue(WatchPriority.Medium), createPriorityQueue(WatchPriority.Low)];
return {
watchFile
};
const lowPollingIntervalQueue = createPollingIntervalQueue(PollingInterval.Low);
const mediumPollingIntervalQueue = createPollingIntervalQueue(PollingInterval.Medium);
const highPollingIntervalQueue = createPollingIntervalQueue(PollingInterval.High);
return watchFile;
function watchFile(fileName: string, callback: FileWatcherCallback, defaultPriority: WatchPriority): FileWatcher {
function watchFile(fileName: string, callback: FileWatcherCallback, defaultPollingInterval: PollingInterval): FileWatcher {
const file: WatchedFile = {
fileName,
callback,
@ -105,31 +116,30 @@ namespace ts {
};
watchedFiles.push(file);
addToPriorityQueue(file, defaultPriority);
addToPollingIntervalQueue(file, defaultPollingInterval);
return {
close: () => {
file.isClosed = true;
// Remove from watchedFiles
unorderedRemoveItem(watchedFiles, file);
// Do not update priority queue since that will happen as part of polling
// Do not update polling interval queue since that will happen as part of polling
}
};
}
function createPriorityQueue(watchPriority: WatchPriority): WatchPriorityQueue {
const queue = [] as WatchPriorityQueue;
queue.watchPriority = watchPriority;
function createPollingIntervalQueue(pollingInterval: PollingInterval): PollingIntervalQueue {
const queue = [] as PollingIntervalQueue;
queue.pollingInterval = pollingInterval;
queue.pollIndex = 0;
queue.pollScheduled = false;
return queue;
}
function pollPriorityQueue(queue: WatchPriorityQueue) {
const priority = queue.watchPriority;
queue.pollIndex = pollQueue(queue, priority, queue.pollIndex, chunkSize(priority));
function pollPollingIntervalQueue(queue: PollingIntervalQueue) {
queue.pollIndex = pollQueue(queue, queue.pollingInterval, queue.pollIndex, chunkSize(queue.pollingInterval));
// Set the next polling index and timeout
if (queue.length) {
scheduleNextPoll(priority);
scheduleNextPoll(queue.pollingInterval);
}
else {
Debug.assert(queue.pollIndex === 0);
@ -137,20 +147,20 @@ namespace ts {
}
}
function pollHighPriorityQueue(queue: WatchPriorityQueue) {
function pollLowPollingIntervalQueue(queue: PollingIntervalQueue) {
// Always poll complete list of changedFilesInLastPoll
pollQueue(changedFilesInLastPoll, WatchPriority.High, /*pollIndex*/ 0, changedFilesInLastPoll.length);
pollQueue(changedFilesInLastPoll, PollingInterval.Low, /*pollIndex*/ 0, changedFilesInLastPoll.length);
// Finally do the actual polling of the queue
pollPriorityQueue(queue);
pollPollingIntervalQueue(queue);
// Schedule poll if there are files in changedFilesInLastPoll but no files in the actual queue
// as pollPriorityQueue wont schedule for next poll
// as pollPollingIntervalQueue wont schedule for next poll
if (!queue.pollScheduled && changedFilesInLastPoll.length) {
scheduleNextPoll(WatchPriority.High);
scheduleNextPoll(PollingInterval.Low);
}
}
function pollQueue(queue: WatchedFile[], priority: WatchPriority, pollIndex: number, chunkSize: number) {
function pollQueue(queue: WatchedFile[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) {
// Max visit would be all elements of the queue
let needsVisit = queue.length;
let definedValueCopyToIndex = pollIndex;
@ -175,22 +185,22 @@ namespace ts {
// Changed files go to changedFilesInLastPoll queue
if (queue !== changedFilesInLastPoll) {
queue[pollIndex] = undefined;
addChangedFileToHighPriorityQueue(watchedFile);
addChangedFileToLowPollingIntervalQueue(watchedFile);
}
}
else if (watchedFile.unchangedPolls !== unChangedThreshold(priority)) {
else if (watchedFile.unchangedPolls !== unChangedThreshold(pollingInterval)) {
watchedFile.unchangedPolls++;
}
else if (queue === changedFilesInLastPoll) {
// Restart unchangedPollCount for unchanged file and move to high priority queue
// Restart unchangedPollCount for unchanged file and move to low polling interval queue
watchedFile.unchangedPolls = 1;
queue[pollIndex] = undefined;
addToPriorityQueue(watchedFile, WatchPriority.High);
addToPollingIntervalQueue(watchedFile, PollingInterval.Low);
}
else if (priority !== WatchPriority.Low) {
else if (pollingInterval !== PollingInterval.High) {
watchedFile.unchangedPolls++;
queue[pollIndex] = undefined;
addToPriorityQueue(watchedFile, priority + 1);
addToPollingIntervalQueue(watchedFile, pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High);
}
if (queue[pollIndex]) {
@ -219,24 +229,35 @@ namespace ts {
}
}
function addToPriorityQueue(file: WatchedFile, priority: WatchPriority) {
priorityQueues[priority].push(file);
scheduleNextPollIfNotAlreadyScheduled(priority);
}
function addChangedFileToHighPriorityQueue(file: WatchedFile) {
changedFilesInLastPoll.push(file);
scheduleNextPollIfNotAlreadyScheduled(WatchPriority.High);
}
function scheduleNextPollIfNotAlreadyScheduled(priority: WatchPriority) {
if (!priorityQueues[priority].pollScheduled) {
scheduleNextPoll(priority);
function pollingIntervalQueue(pollingInterval: PollingInterval) {
switch (pollingInterval) {
case PollingInterval.Low:
return lowPollingIntervalQueue;
case PollingInterval.Medium:
return mediumPollingIntervalQueue;
case PollingInterval.High:
return highPollingIntervalQueue;
}
}
function scheduleNextPoll(priority: WatchPriority) {
priorityQueues[priority].pollScheduled = host.setTimeout(priority === WatchPriority.High ? pollHighPriorityQueue : pollPriorityQueue, pollingInterval(priority), priorityQueues[priority]);
function addToPollingIntervalQueue(file: WatchedFile, pollingInterval: PollingInterval) {
pollingIntervalQueue(pollingInterval).push(file);
scheduleNextPollIfNotAlreadyScheduled(pollingInterval);
}
function addChangedFileToLowPollingIntervalQueue(file: WatchedFile) {
changedFilesInLastPoll.push(file);
scheduleNextPollIfNotAlreadyScheduled(PollingInterval.Low);
}
function scheduleNextPollIfNotAlreadyScheduled(pollingInterval: PollingInterval) {
if (!pollingIntervalQueue(pollingInterval).pollScheduled) {
scheduleNextPoll(pollingInterval);
}
}
function scheduleNextPoll(pollingInterval: PollingInterval) {
pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval));
}
function getModifiedTime(fileName: string) {
@ -381,6 +402,7 @@ namespace ts {
}
const useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
const tscWatchOption = process.env.TSC_WATCHOPTION;
const nodeSystem: System = {
args: process.argv.slice(2),
@ -391,20 +413,6 @@ namespace ts {
},
readFile,
writeFile,
watchFile: useNonPollingWatchers ? createNonPollingWatchFile() : fsWatchFile,
watchDirectory: (directoryName, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return fsWatchDirectory(directoryName, (eventName, relativeFileName) => {
// In watchDirectory we only care about adding and removing files (when event name is
// "rename"); changes made within files are handled by corresponding fileWatchers (when
// event name is "change")
if (eventName === "rename") {
// When deleting a file, the passed baseFileName is null
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(directoryName, relativeFileName)));
}
}, recursive);
},
resolvePath: path => _path.resolve(path),
fileExists,
directoryExists,
@ -474,6 +482,20 @@ namespace ts {
process.stdout.write("\x1Bc");
}
};
nodeSystem.watchFile = getWatchFile();
nodeSystem.watchDirectory = (directoryName, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return fsWatchDirectory(directoryName, (eventName, relativeFileName) => {
// In watchDirectory we only care about adding and removing files (when event name is
// "rename"); changes made within files are handled by corresponding fileWatchers (when
// event name is "change")
if (eventName === "rename") {
// When deleting a file, the passed baseFileName is null
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(directoryName, relativeFileName)));
}
}, recursive);
};
return nodeSystem;
function isFileSystemCaseSensitive(): boolean {
@ -493,6 +515,20 @@ namespace ts {
});
}
function getWatchFile(): HostWatchFile {
switch (tscWatchOption) {
case "PriorityPollingInterval":
// Use polling interval based on priority when create watch using host.watchFile
return fsWatchFile;
case "DynamicPriorityPolling":
return createDynamicPriorityPollingWatchFile(nodeSystem);
}
return useNonPollingWatchers ?
createNonPollingWatchFile() :
// Default to do not use polling interval as it is before this experiment branch
(fileName, callback) => fsWatchFile(fileName, callback);
}
function createNonPollingWatchFile() {
// One file can have multiple watchers
const fileWatcherCallbacks = createMultiMap<FileWatcherCallback>();

View File

@ -257,11 +257,11 @@ namespace ts {
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? s => { system.write(s); system.write(system.newLine); } : noop;
watchingHost = watchingHost || createWatchingSystemHost(compilerOptions.pretty);
const { system, parseConfigFile, reportDiagnostic, reportWatchDiagnostic, beforeCompile, afterCompile } = watchingHost;
const { watchFile, watchFilePath, watchDirectory: watchDirectoryWorker } = getWatchFactory(system, watchLogLevel, writeLog);
const { watchFile, watchFilePath, watchDirectory: watchDirectoryWorker } = getWatchFactory(watchLogLevel, writeLog);
const directoryStructureHost = configFileName ? createCachedDirectoryStructureHost(system) : system;
if (configFileName) {
watchFile(system, configFileName, scheduleProgramReload, WatchPriority.Low);
watchFile(system, configFileName, scheduleProgramReload, PollingInterval.High);
}
const getCurrentDirectory = memoize(() => directoryStructureHost.getCurrentDirectory());
@ -414,7 +414,7 @@ namespace ts {
hostSourceFile.sourceFile = sourceFile;
sourceFile.version = hostSourceFile.version.toString();
if (!hostSourceFile.fileWatcher) {
hostSourceFile.fileWatcher = watchFilePath(system, fileName, onSourceFileChange, WatchPriority.High, path);
hostSourceFile.fileWatcher = watchFilePath(system, fileName, onSourceFileChange, PollingInterval.Low, path);
}
}
else {
@ -427,7 +427,7 @@ namespace ts {
let fileWatcher: FileWatcher;
if (sourceFile) {
sourceFile.version = "0";
fileWatcher = watchFilePath(system, fileName, onSourceFileChange, WatchPriority.High, path);
fileWatcher = watchFilePath(system, fileName, onSourceFileChange, PollingInterval.Low, path);
sourceFilesCache.set(path, { sourceFile, version: 0, fileWatcher });
}
else {
@ -601,7 +601,7 @@ namespace ts {
}
function watchMissingFilePath(missingFilePath: Path) {
return watchFilePath(system, missingFilePath, onMissingFileChange, WatchPriority.Medium, missingFilePath);
return watchFilePath(system, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath);
}
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {

View File

@ -96,9 +96,9 @@ namespace ts {
Verbose
}
export type WatchFile<X, Y> = (host: System, file: string, callback: FileWatcherCallback, watchPriority: WatchPriority, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchFile<X, Y> = (host: System, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type FilePathWatcherCallback = (fileName: string, eventKind: FileWatcherEventKind, filePath: Path) => void;
export type WatchFilePath<X, Y> = (host: System, file: string, callback: FilePathWatcherCallback, watchPriority: WatchPriority, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchFilePath<X, Y> = (host: System, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchDirectory<X, Y> = (host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export interface WatchFactory<X, Y> {
@ -107,30 +107,15 @@ namespace ts {
watchDirectory: WatchDirectory<X, Y>;
}
export function getWatchFactory<X = undefined, Y = undefined>(host: System, watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo<X, Y>): WatchFactory<X, Y> {
const value = host.getEnvironmentVariable && host.getEnvironmentVariable("TSC_WATCHFILE");
switch (value) {
case "PriorityPollingInterval":
// Use polling interval based on priority when create watch using host.watchFile
return getWatchFactoryWith(watchLogLevel, log, getDetailWatchInfo, watchFileUsingPriorityPollingInterval, watchDirectory);
case "DynamicPriorityPolling":
// Dynamically move frequently changing files to high frequency polling and non changing files to lower frequency
return getWatchFactoryWithDynamicPriorityPolling(host, watchLogLevel, log, getDetailWatchInfo);
default:
return getDefaultWatchFactory(watchLogLevel, log, getDetailWatchInfo);
}
}
export function getDefaultWatchFactory<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo<X, Y>): WatchFactory<X, Y> {
// Current behaviour in which polling interval is always 250 ms
export function getWatchFactory<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo<X, Y>): WatchFactory<X, Y> {
return getWatchFactoryWith(watchLogLevel, log, getDetailWatchInfo, watchFile, watchDirectory);
}
function getWatchFactoryWith<X = undefined, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined,
watchFile: (host: System, file: string, callback: FileWatcherCallback, watchPriority: WatchPriority) => FileWatcher,
watchFile: (host: System, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
watchDirectory: (host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
const createFileWatcher: CreateFileWatcher<WatchPriority, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
const createFilePathWatcher: CreateFileWatcher<WatchPriority, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
const createFileWatcher: CreateFileWatcher<PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
const createFilePathWatcher: CreateFileWatcher<PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
return {
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
@ -141,22 +126,13 @@ namespace ts {
createDirectoryWatcher(host, directory, callback, flags, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo)
};
function watchFilePath(host: System, file: string, callback: FilePathWatcherCallback, watchPriority: WatchPriority, path: Path): FileWatcher {
return watchFile(host, file, (fileName, eventKind) => callback(fileName, eventKind, path), watchPriority);
function watchFilePath(host: System, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path): FileWatcher {
return watchFile(host, file, (fileName, eventKind) => callback(fileName, eventKind, path), pollingInterval);
}
}
function getWatchFactoryWithDynamicPriorityPolling<X = undefined, Y = undefined>(host: System, watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo?: GetDetailWatchInfo<X, Y>): WatchFactory<X, Y> {
const pollingSet = createDynamicPriorityPollingStatsSet(host);
return getWatchFactoryWith(watchLogLevel, log, getDetailWatchInfo, watchFile, watchDirectory);
function watchFile(_host: System, file: string, callback: FileWatcherCallback, watchPriority: WatchPriority): FileWatcher {
return pollingSet.watchFile(file, callback, watchPriority);
}
}
function watchFile(host: System, file: string, callback: FileWatcherCallback, _watchPriority: WatchPriority): FileWatcher {
return host.watchFile(file, callback);
function watchFile(host: System, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval): FileWatcher {
return host.watchFile(file, callback, pollingInterval);
}
function watchDirectory(host: System, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher {

View File

@ -2123,15 +2123,15 @@ declare module "fs" {
};
const files = [file1, libFile];
const environmentVariables = createMap<string>();
environmentVariables.set("TSC_WATCHFILE", "DynamicPriorityPolling");
environmentVariables.set("TSC_WATCHOPTION", "DynamicPriorityPolling");
const host = createWatchedSystem(files, { environmentVariables });
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const initialProgram = watch();
verifyProgram();
const mediumPriorityThreshold = unChangedThreshold(WatchPriority.Medium);
for (let index = 0; index < mediumPriorityThreshold; index++) {
const mediumPollingIntervalThreshold = unChangedThreshold(PollingInterval.Medium);
for (let index = 0; index < mediumPollingIntervalThreshold; index++) {
// Transition libFile and file1 to low priority queue
host.checkTimeoutQueueLengthAndRun(1);
assert.deepEqual(watch(), initialProgram);
@ -2157,14 +2157,14 @@ declare module "fs" {
assert.isTrue(host.fileExists(outputFile1));
assert.equal(host.readFile(outputFile1), file1.content + host.newLine);
const newThreshold = unChangedThreshold(WatchPriority.High) + mediumPriorityThreshold;
const newThreshold = unChangedThreshold(PollingInterval.Low) + mediumPollingIntervalThreshold;
for (; fileUnchangeDetected < newThreshold; fileUnchangeDetected++) {
// For low + Medium/high priority
// For high + Medium/low polling interval
host.checkTimeoutQueueLengthAndRun(2);
assert.deepEqual(watch(), newProgram);
}
// Everything goes in low priority queue
// Everything goes in high polling interval queue
host.checkTimeoutQueueLengthAndRun(1);
assert.deepEqual(watch(), newProgram);

View File

@ -262,6 +262,7 @@ interface Array<T> {}`
readonly watchedFiles = createMultiMap<TestFileWatcher>();
private readonly executingFilePath: string;
private readonly currentDirectory: string;
private readonly dynamicPriorityWatchFile: HostWatchFile;
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray<FileOrFolder>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
@ -269,6 +270,9 @@ interface Array<T> {}`
this.executingFilePath = this.getHostSpecificPath(executingFilePath);
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
this.reloadFS(fileOrFolderList);
this.dynamicPriorityWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHOPTION") === "DynamicPriorityPolling" ?
createDynamicPriorityPollingWatchFile(this) :
undefined;
}
getNewLine() {
@ -602,7 +606,11 @@ interface Array<T> {}`
return Harness.mockHash(s);
}
watchFile(fileName: string, cb: FileWatcherCallback) {
watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) {
if (this.dynamicPriorityWatchFile) {
return this.dynamicPriorityWatchFile(fileName, cb, pollingInterval);
}
const path = this.toFullPath(fileName);
const callback: TestFileWatcher = { fileName, cb };
this.watchedFiles.add(path, callback);

View File

@ -449,7 +449,7 @@ namespace ts.server {
const watchLogLevel = this.logger.hasLevel(LogLevel.verbose) ? WatchLogLevel.Verbose :
this.logger.loggingEnabled() ? WatchLogLevel.TriggerOnly : WatchLogLevel.None;
const log: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => this.logger.info(s)) : noop;
this.watchFactory = getDefaultWatchFactory(watchLogLevel, log, getDetailWatchInfo);
this.watchFactory = getWatchFactory(watchLogLevel, log, getDetailWatchInfo);
}
toPath(fileName: string) {
@ -1116,7 +1116,7 @@ namespace ts.server {
this.host,
configFileName,
(_filename, eventKind) => this.onConfigFileChangeForOpenScriptInfo(configFileName, eventKind),
WatchPriority.Low,
PollingInterval.High,
WatchType.ConfigFileForInferredRoot
);
this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.UpdatedCallback);
@ -1500,7 +1500,7 @@ namespace ts.server {
this.host,
configFileName,
(_fileName, eventKind) => this.onConfigChangedForConfiguredProject(project, eventKind),
WatchPriority.Low,
PollingInterval.High,
WatchType.ConfigFilePath,
project
);
@ -1727,7 +1727,7 @@ namespace ts.server {
this.host,
fileName,
(fileName, eventKind, path) => this.onSourceFileChanged(fileName, eventKind, path),
WatchPriority.Medium,
PollingInterval.Medium,
info.path,
WatchType.ClosedScriptInfo
);

View File

@ -932,7 +932,7 @@ namespace ts.server {
this.projectService.delayUpdateProjectGraphAndInferredProjectsRefresh(this);
}
},
WatchPriority.Medium,
PollingInterval.Medium,
WatchType.MissingFilePath,
this
);