mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:32:08 -06:00
Move fixed chunk size polling as a watch option and move it out of server (#42542)
* Move fixed chunk size polling as a watch option and move it out of server Fixes #41549 * Feedback
This commit is contained in:
parent
5dbb110497
commit
0cf834ceec
@ -101,11 +101,12 @@ namespace ts {
|
||||
fixedpollinginterval: WatchFileKind.FixedPollingInterval,
|
||||
prioritypollinginterval: WatchFileKind.PriorityPollingInterval,
|
||||
dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling,
|
||||
fixedchunksizepolling: WatchFileKind.FixedChunkSizePolling,
|
||||
usefsevents: WatchFileKind.UseFsEvents,
|
||||
usefseventsonparentdirectory: WatchFileKind.UseFsEventsOnParentDirectory,
|
||||
})),
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Specify_strategy_for_watching_file_Colon_FixedPollingInterval_default_PriorityPollingInterval_DynamicPriorityPolling_UseFsEvents_UseFsEventsOnParentDirectory,
|
||||
description: Diagnostics.Specify_strategy_for_watching_file_Colon_FixedPollingInterval_default_PriorityPollingInterval_DynamicPriorityPolling_FixedChunkSizePolling_UseFsEvents_UseFsEventsOnParentDirectory,
|
||||
},
|
||||
{
|
||||
name: "watchDirectory",
|
||||
@ -113,9 +114,10 @@ namespace ts {
|
||||
usefsevents: WatchDirectoryKind.UseFsEvents,
|
||||
fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval,
|
||||
dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling,
|
||||
fixedchunksizepolling: WatchDirectoryKind.FixedChunkSizePolling,
|
||||
})),
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Specify_strategy_for_watching_directory_on_platforms_that_don_t_support_recursive_watching_natively_Colon_UseFsEvents_default_FixedPollingInterval_DynamicPriorityPolling,
|
||||
description: Diagnostics.Specify_strategy_for_watching_directory_on_platforms_that_don_t_support_recursive_watching_natively_Colon_UseFsEvents_default_FixedPollingInterval_DynamicPriorityPolling_FixedChunkSizePolling,
|
||||
},
|
||||
{
|
||||
name: "fallbackPolling",
|
||||
@ -123,9 +125,10 @@ namespace ts {
|
||||
fixedinterval: PollingWatchKind.FixedInterval,
|
||||
priorityinterval: PollingWatchKind.PriorityInterval,
|
||||
dynamicpriority: PollingWatchKind.DynamicPriority,
|
||||
fixedchunksize: PollingWatchKind.FixedChunkSize,
|
||||
})),
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Specify_strategy_for_creating_a_polling_watch_when_it_fails_to_create_using_file_system_events_Colon_FixedInterval_default_PriorityInterval_DynamicPriority,
|
||||
description: Diagnostics.Specify_strategy_for_creating_a_polling_watch_when_it_fails_to_create_using_file_system_events_Colon_FixedInterval_default_PriorityInterval_DynamicPriority_FixedChunkSize,
|
||||
},
|
||||
{
|
||||
name: "synchronousWatchDirectory",
|
||||
|
||||
@ -4701,15 +4701,15 @@
|
||||
"category": "Message",
|
||||
"code": 6224
|
||||
},
|
||||
"Specify strategy for watching file: 'FixedPollingInterval' (default), 'PriorityPollingInterval', 'DynamicPriorityPolling', 'UseFsEvents', 'UseFsEventsOnParentDirectory'.": {
|
||||
"Specify strategy for watching file: 'FixedPollingInterval' (default), 'PriorityPollingInterval', 'DynamicPriorityPolling', 'FixedChunkSizePolling', 'UseFsEvents', 'UseFsEventsOnParentDirectory'.": {
|
||||
"category": "Message",
|
||||
"code": 6225
|
||||
},
|
||||
"Specify strategy for watching directory on platforms that don't support recursive watching natively: 'UseFsEvents' (default), 'FixedPollingInterval', 'DynamicPriorityPolling'.": {
|
||||
"Specify strategy for watching directory on platforms that don't support recursive watching natively: 'UseFsEvents' (default), 'FixedPollingInterval', 'DynamicPriorityPolling', 'FixedChunkSizePolling'.": {
|
||||
"category": "Message",
|
||||
"code": 6226
|
||||
},
|
||||
"Specify strategy for creating a polling watch when it fails to create using file system events: 'FixedInterval' (default), 'PriorityInterval', 'DynamicPriority'.": {
|
||||
"Specify strategy for creating a polling watch when it fails to create using file system events: 'FixedInterval' (default), 'PriorityInterval', 'DynamicPriority', 'FixedChunkSize'.": {
|
||||
"category": "Message",
|
||||
"code": 6227
|
||||
},
|
||||
|
||||
@ -57,6 +57,11 @@ namespace ts {
|
||||
/* @internal */
|
||||
export const missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time
|
||||
|
||||
/* @internal */
|
||||
export function getModifiedTime(host: { getModifiedTime: NonNullable<System["getModifiedTime"]>; }, fileName: string) {
|
||||
return host.getModifiedTime(fileName) || missingFileModifiedTime;
|
||||
}
|
||||
|
||||
interface Levels {
|
||||
Low: number;
|
||||
Medium: number;
|
||||
@ -126,6 +131,64 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
interface WatchedFileWithIsClosed extends WatchedFile {
|
||||
isClosed?: boolean;
|
||||
}
|
||||
function pollWatchedFileQueue<T extends WatchedFileWithIsClosed>(
|
||||
host: { getModifiedTime: NonNullable<System["getModifiedTime"]>; },
|
||||
queue: (T | undefined)[],
|
||||
pollIndex: number, chunkSize: number,
|
||||
callbackOnWatchFileStat?: (watchedFile: T, pollIndex: number, fileChanged: boolean) => void
|
||||
) {
|
||||
let definedValueCopyToIndex = pollIndex;
|
||||
// Max visit would be all elements of the queue
|
||||
for (let canVisit = queue.length; chunkSize && canVisit; nextPollIndex(), canVisit--) {
|
||||
const watchedFile = queue[pollIndex];
|
||||
if (!watchedFile) {
|
||||
continue;
|
||||
}
|
||||
else if (watchedFile.isClosed) {
|
||||
queue[pollIndex] = undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only files polled count towards chunkSize
|
||||
chunkSize--;
|
||||
const fileChanged = onWatchedFileStat(watchedFile, getModifiedTime(host, watchedFile.fileName));
|
||||
if (watchedFile.isClosed) {
|
||||
// Closed watcher as part of callback
|
||||
queue[pollIndex] = undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
callbackOnWatchFileStat?.(watchedFile, pollIndex, fileChanged);
|
||||
// Defragment the queue while we are at it
|
||||
if (queue[pollIndex]) {
|
||||
// Copy this file to the non hole location
|
||||
if (definedValueCopyToIndex < pollIndex) {
|
||||
queue[definedValueCopyToIndex] = watchedFile;
|
||||
queue[pollIndex] = undefined;
|
||||
}
|
||||
definedValueCopyToIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return next poll index
|
||||
return pollIndex;
|
||||
|
||||
function nextPollIndex() {
|
||||
pollIndex++;
|
||||
if (pollIndex === queue.length) {
|
||||
if (definedValueCopyToIndex < pollIndex) {
|
||||
// There are holes from definedValueCopyToIndex to end of queue, change queue size
|
||||
queue.length = definedValueCopyToIndex;
|
||||
}
|
||||
pollIndex = 0;
|
||||
definedValueCopyToIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createDynamicPriorityPollingWatchFile(host: {
|
||||
getModifiedTime: NonNullable<System["getModifiedTime"]>;
|
||||
@ -154,7 +217,7 @@ namespace ts {
|
||||
fileName,
|
||||
callback,
|
||||
unchangedPolls: 0,
|
||||
mtime: getModifiedTime(fileName)
|
||||
mtime: getModifiedTime(host, fileName)
|
||||
};
|
||||
watchedFiles.push(file);
|
||||
|
||||
@ -203,26 +266,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function pollQueue(queue: (WatchedFile | undefined)[], pollingInterval: PollingInterval, pollIndex: number, chunkSize: number) {
|
||||
// Max visit would be all elements of the queue
|
||||
let needsVisit = queue.length;
|
||||
let definedValueCopyToIndex = pollIndex;
|
||||
for (let polled = 0; polled < chunkSize && needsVisit > 0; nextPollIndex(), needsVisit--) {
|
||||
const watchedFile = queue[pollIndex];
|
||||
if (!watchedFile) {
|
||||
continue;
|
||||
}
|
||||
else if (watchedFile.isClosed) {
|
||||
queue[pollIndex] = undefined;
|
||||
continue;
|
||||
}
|
||||
return pollWatchedFileQueue(
|
||||
host,
|
||||
queue,
|
||||
pollIndex,
|
||||
chunkSize,
|
||||
onWatchFileStat
|
||||
);
|
||||
|
||||
polled++;
|
||||
const fileChanged = onWatchedFileStat(watchedFile, getModifiedTime(watchedFile.fileName));
|
||||
if (watchedFile.isClosed) {
|
||||
// Closed watcher as part of callback
|
||||
queue[pollIndex] = undefined;
|
||||
}
|
||||
else if (fileChanged) {
|
||||
function onWatchFileStat(watchedFile: WatchedFile, pollIndex: number, fileChanged: boolean) {
|
||||
if (fileChanged) {
|
||||
watchedFile.unchangedPolls = 0;
|
||||
// Changed files go to changedFilesInLastPoll queue
|
||||
if (queue !== changedFilesInLastPoll) {
|
||||
@ -244,30 +297,6 @@ namespace ts {
|
||||
queue[pollIndex] = undefined;
|
||||
addToPollingIntervalQueue(watchedFile, pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High);
|
||||
}
|
||||
|
||||
if (queue[pollIndex]) {
|
||||
// Copy this file to the non hole location
|
||||
if (definedValueCopyToIndex < pollIndex) {
|
||||
queue[definedValueCopyToIndex] = watchedFile;
|
||||
queue[pollIndex] = undefined;
|
||||
}
|
||||
definedValueCopyToIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return next poll index
|
||||
return pollIndex;
|
||||
|
||||
function nextPollIndex() {
|
||||
pollIndex++;
|
||||
if (pollIndex === queue.length) {
|
||||
if (definedValueCopyToIndex < pollIndex) {
|
||||
// There are holes from nextDefinedValueIndex to end of queue, change queue size
|
||||
queue.length = definedValueCopyToIndex;
|
||||
}
|
||||
pollIndex = 0;
|
||||
definedValueCopyToIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,10 +330,6 @@ namespace ts {
|
||||
function scheduleNextPoll(pollingInterval: PollingInterval) {
|
||||
pollingIntervalQueue(pollingInterval).pollScheduled = host.setTimeout(pollingInterval === PollingInterval.Low ? pollLowPollingIntervalQueue : pollPollingIntervalQueue, pollingInterval, pollingIntervalQueue(pollingInterval));
|
||||
}
|
||||
|
||||
function getModifiedTime(fileName: string) {
|
||||
return host.getModifiedTime(fileName) || missingFileModifiedTime;
|
||||
}
|
||||
}
|
||||
|
||||
function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSensitiveFileNames: boolean): HostWatchFile {
|
||||
@ -361,6 +386,43 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createFixedChunkSizePollingWatchFile(host: {
|
||||
getModifiedTime: NonNullable<System["getModifiedTime"]>;
|
||||
setTimeout: NonNullable<System["setTimeout"]>;
|
||||
}): HostWatchFile {
|
||||
const watchedFiles: (WatchedFileWithIsClosed | undefined)[] = [];
|
||||
let pollIndex = 0;
|
||||
let pollScheduled: any;
|
||||
return watchFile;
|
||||
|
||||
function watchFile(fileName: string, callback: FileWatcherCallback): FileWatcher {
|
||||
const file: WatchedFileWithIsClosed = {
|
||||
fileName,
|
||||
callback,
|
||||
mtime: getModifiedTime(host, fileName)
|
||||
};
|
||||
watchedFiles.push(file);
|
||||
scheduleNextPoll();
|
||||
return {
|
||||
close: () => {
|
||||
file.isClosed = true;
|
||||
unorderedRemoveItem(watchedFiles, file);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function pollQueue() {
|
||||
pollScheduled = undefined;
|
||||
pollIndex = pollWatchedFileQueue(host, watchedFiles, pollIndex, pollingChunkSize[PollingInterval.Low]);
|
||||
scheduleNextPoll();
|
||||
}
|
||||
|
||||
function scheduleNextPoll() {
|
||||
if (!watchedFiles.length || pollScheduled) return;
|
||||
pollScheduled = host.setTimeout(pollQueue, PollingInterval.High);
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createSingleFileWatcherPerName(
|
||||
watchFile: HostWatchFile,
|
||||
@ -795,6 +857,7 @@ namespace ts {
|
||||
tscWatchFile: string | undefined;
|
||||
useNonPollingWatchers?: boolean;
|
||||
tscWatchDirectory: string | undefined;
|
||||
defaultWatchFileKind: System["defaultWatchFileKind"];
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
@ -814,8 +877,10 @@ namespace ts {
|
||||
tscWatchFile,
|
||||
useNonPollingWatchers,
|
||||
tscWatchDirectory,
|
||||
defaultWatchFileKind,
|
||||
}: CreateSystemWatchFunctions): { watchFile: HostWatchFile; watchDirectory: HostWatchDirectory; } {
|
||||
let dynamicPollingWatchFile: HostWatchFile | undefined;
|
||||
let fixedChunkSizePollingWatchFile: HostWatchFile | undefined;
|
||||
let nonPollingWatchFile: HostWatchFile | undefined;
|
||||
let hostRecursiveDirectoryWatcher: HostWatchDirectory | undefined;
|
||||
return {
|
||||
@ -833,6 +898,8 @@ namespace ts {
|
||||
return pollingWatchFile(fileName, callback, pollingInterval, /*options*/ undefined);
|
||||
case WatchFileKind.DynamicPriorityPolling:
|
||||
return ensureDynamicPollingWatchFile()(fileName, callback, pollingInterval, /*options*/ undefined);
|
||||
case WatchFileKind.FixedChunkSizePolling:
|
||||
return ensureFixedChunkSizePollingWatchFile()(fileName, callback, /* pollingInterval */ undefined!, /*options*/ undefined);
|
||||
case WatchFileKind.UseFsEvents:
|
||||
return fsWatch(
|
||||
fileName,
|
||||
@ -853,8 +920,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function ensureDynamicPollingWatchFile() {
|
||||
return dynamicPollingWatchFile ||
|
||||
(dynamicPollingWatchFile = createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout }));
|
||||
return dynamicPollingWatchFile ||= createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout });
|
||||
}
|
||||
|
||||
function ensureFixedChunkSizePollingWatchFile() {
|
||||
return fixedChunkSizePollingWatchFile ||= createFixedChunkSizePollingWatchFile({ getModifiedTime, setTimeout });
|
||||
}
|
||||
|
||||
function updateOptionsForWatchFile(options: WatchOptions | undefined, useNonPollingWatchers?: boolean): WatchOptions {
|
||||
@ -880,7 +950,7 @@ namespace ts {
|
||||
// Use notifications from FS to watch with falling back to fs.watchFile
|
||||
generateWatchFileOptions(WatchFileKind.UseFsEventsOnParentDirectory, PollingWatchKind.PriorityInterval, options) :
|
||||
// Default to do not use fixed polling interval
|
||||
{ watchFile: WatchFileKind.FixedPollingInterval };
|
||||
{ watchFile: defaultWatchFileKind?.() || WatchFileKind.FixedPollingInterval };
|
||||
}
|
||||
}
|
||||
|
||||
@ -944,6 +1014,13 @@ namespace ts {
|
||||
PollingInterval.Medium,
|
||||
/*options*/ undefined
|
||||
);
|
||||
case WatchDirectoryKind.FixedChunkSizePolling:
|
||||
return ensureFixedChunkSizePollingWatchFile()(
|
||||
directoryName,
|
||||
() => callback(directoryName),
|
||||
/* pollingInterval */ undefined!,
|
||||
/*options*/ undefined
|
||||
);
|
||||
case WatchDirectoryKind.UseFsEvents:
|
||||
return fsWatch(
|
||||
directoryName,
|
||||
@ -1131,6 +1208,7 @@ namespace ts {
|
||||
// For testing
|
||||
/*@internal*/ now?(): Date;
|
||||
/*@internal*/ require?(baseDir: string, moduleName: string): RequireResult;
|
||||
/*@internal*/ defaultWatchFileKind?(): WatchFileKind | undefined;
|
||||
}
|
||||
|
||||
export interface FileWatcher {
|
||||
@ -1219,6 +1297,7 @@ namespace ts {
|
||||
tscWatchFile: process.env.TSC_WATCHFILE,
|
||||
useNonPollingWatchers: process.env.TSC_NONPOLLING_WATCHER,
|
||||
tscWatchDirectory: process.env.TSC_WATCHDIRECTORY,
|
||||
defaultWatchFileKind: () => sys!.defaultWatchFileKind?.(),
|
||||
});
|
||||
const nodeSystem: System = {
|
||||
args: process.argv.slice(2),
|
||||
|
||||
@ -1334,7 +1334,7 @@ namespace ts {
|
||||
|
||||
function checkConfigFileUpToDateStatus(state: SolutionBuilderState, configFile: string, oldestOutputFileTime: Date, oldestOutputFileName: string): Status.OutOfDateWithSelf | undefined {
|
||||
// Check tsconfig time
|
||||
const tsconfigTime = state.host.getModifiedTime(configFile) || missingFileModifiedTime;
|
||||
const tsconfigTime = getModifiedTime(state.host, configFile);
|
||||
if (oldestOutputFileTime < tsconfigTime) {
|
||||
return {
|
||||
type: UpToDateStatusType.OutOfDateWithSelf,
|
||||
@ -1357,7 +1357,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
const inputTime = host.getModifiedTime(inputFile) || missingFileModifiedTime;
|
||||
const inputTime = getModifiedTime(host, inputFile); host.getModifiedTime(inputFile);
|
||||
if (inputTime > newestInputFileTime) {
|
||||
newestInputFileName = inputFile;
|
||||
newestInputFileTime = inputTime;
|
||||
@ -1390,7 +1390,7 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
|
||||
const outputTime = host.getModifiedTime(output) || missingFileModifiedTime;
|
||||
const outputTime = getModifiedTime(host, output);
|
||||
if (outputTime < oldestOutputFileTime) {
|
||||
oldestOutputFileTime = outputTime;
|
||||
oldestOutputFileName = output;
|
||||
@ -1413,7 +1413,7 @@ namespace ts {
|
||||
// had its file touched but not had its contents changed - this allows us
|
||||
// to skip a downstream typecheck
|
||||
if (isDeclarationFile(output)) {
|
||||
const outputModifiedTime = host.getModifiedTime(output) || missingFileModifiedTime;
|
||||
const outputModifiedTime = getModifiedTime(host, output);
|
||||
newestDeclarationFileContentChangedTime = newer(newestDeclarationFileContentChangedTime, outputModifiedTime);
|
||||
}
|
||||
}
|
||||
@ -1571,7 +1571,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isDeclarationFile(file)) {
|
||||
priorNewestUpdateTime = newer(priorNewestUpdateTime, host.getModifiedTime(file) || missingFileModifiedTime);
|
||||
priorNewestUpdateTime = newer(priorNewestUpdateTime, getModifiedTime(host, file));
|
||||
}
|
||||
|
||||
host.setModifiedTime(file, now);
|
||||
|
||||
@ -5795,6 +5795,7 @@ namespace ts {
|
||||
FixedPollingInterval,
|
||||
PriorityPollingInterval,
|
||||
DynamicPriorityPolling,
|
||||
FixedChunkSizePolling,
|
||||
UseFsEvents,
|
||||
UseFsEventsOnParentDirectory,
|
||||
}
|
||||
@ -5803,12 +5804,14 @@ namespace ts {
|
||||
UseFsEvents,
|
||||
FixedPollingInterval,
|
||||
DynamicPriorityPolling,
|
||||
FixedChunkSizePolling,
|
||||
}
|
||||
|
||||
export enum PollingWatchKind {
|
||||
FixedInterval,
|
||||
PriorityInterval,
|
||||
DynamicPriority,
|
||||
FixedChunkSize,
|
||||
}
|
||||
|
||||
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
|
||||
|
||||
@ -395,6 +395,7 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
private readonly executingFilePath: string;
|
||||
private readonly currentDirectory: string;
|
||||
public require: ((initialPath: string, moduleName: string) => RequireResult) | undefined;
|
||||
public defaultWatchFileKind?: () => WatchFileKind | undefined;
|
||||
watchFile: HostWatchFile;
|
||||
watchDirectory: HostWatchDirectory;
|
||||
constructor(
|
||||
@ -439,7 +440,8 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
getAccessibleSortedChildDirectories: path => this.getDirectories(path),
|
||||
realpath: this.realpath.bind(this),
|
||||
tscWatchFile,
|
||||
tscWatchDirectory
|
||||
tscWatchDirectory,
|
||||
defaultWatchFileKind: () => this.defaultWatchFileKind?.(),
|
||||
});
|
||||
this.watchFile = watchFile;
|
||||
this.watchDirectory = watchDirectory;
|
||||
|
||||
@ -1538,6 +1538,7 @@ namespace ts.server.protocol {
|
||||
FixedPollingInterval = "FixedPollingInterval",
|
||||
PriorityPollingInterval = "PriorityPollingInterval",
|
||||
DynamicPriorityPolling = "DynamicPriorityPolling",
|
||||
FixedChunkSizePolling = "FixedChunkSizePolling",
|
||||
UseFsEvents = "UseFsEvents",
|
||||
UseFsEventsOnParentDirectory = "UseFsEventsOnParentDirectory",
|
||||
}
|
||||
@ -1546,12 +1547,14 @@ namespace ts.server.protocol {
|
||||
UseFsEvents = "UseFsEvents",
|
||||
FixedPollingInterval = "FixedPollingInterval",
|
||||
DynamicPriorityPolling = "DynamicPriorityPolling",
|
||||
FixedChunkSizePolling = "FixedChunkSizePolling",
|
||||
}
|
||||
|
||||
export const enum PollingWatchKind {
|
||||
FixedInterval = "FixedInterval",
|
||||
PriorityInterval = "PriorityInterval",
|
||||
DynamicPriority = "DynamicPriority",
|
||||
FixedChunkSize = "FixedChunkSize",
|
||||
}
|
||||
|
||||
export interface WatchOptions {
|
||||
|
||||
@ -650,7 +650,7 @@ namespace ts {
|
||||
length: undefined
|
||||
},
|
||||
{
|
||||
messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority'.",
|
||||
messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority', 'fixedchunksize'.",
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
file: undefined,
|
||||
@ -957,7 +957,7 @@ namespace ts {
|
||||
length: undefined
|
||||
},
|
||||
{
|
||||
messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority'.",
|
||||
messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority', 'fixedchunksize'.",
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
file: undefined,
|
||||
|
||||
@ -66,6 +66,90 @@ namespace ts.tscWatch {
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: "watchFile/using fixed chunk size polling",
|
||||
commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"],
|
||||
sys: () => {
|
||||
const configFile: File = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: JSON.stringify({
|
||||
watchOptions: {
|
||||
watchFile: "FixedChunkSizePolling"
|
||||
}
|
||||
})
|
||||
};
|
||||
const files = [libFile, commonFile1, commonFile2, configFile];
|
||||
return createWatchedSystem(files);
|
||||
},
|
||||
changes: [
|
||||
{
|
||||
caption: "The timeout is to check the status of all files",
|
||||
change: noop,
|
||||
timeouts: (sys, programs) => {
|
||||
// On each timeout file does not change
|
||||
const initialProgram = programs[0][0];
|
||||
for (let index = 0; index < 4; index++) {
|
||||
sys.checkTimeoutQueueLengthAndRun(1);
|
||||
assert.deepEqual(programs[0][0], initialProgram);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "Make change to file but should detect as changed and schedule program update",
|
||||
// Make a change to file
|
||||
change: sys => sys.writeFile(commonFile1.path, "var zz30 = 100;"),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
},
|
||||
{
|
||||
caption: "Callbacks: queue and scheduled program update",
|
||||
change: noop,
|
||||
// Callbacks: scheduled program update and queue for the polling
|
||||
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
|
||||
},
|
||||
{
|
||||
caption: "The timeout is to check the status of all files",
|
||||
change: noop,
|
||||
timeouts: (sys, programs) => {
|
||||
// On each timeout file does not change
|
||||
const initialProgram = programs[0][0];
|
||||
sys.checkTimeoutQueueLengthAndRun(1);
|
||||
assert.deepEqual(programs[0][0], initialProgram);
|
||||
},
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: "watchFile/setting default as fixed chunk size watch file works",
|
||||
commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"],
|
||||
sys: () => {
|
||||
const configFile: File = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: "{}"
|
||||
};
|
||||
const files = [libFile, commonFile1, commonFile2, configFile];
|
||||
const sys = createWatchedSystem(files);
|
||||
sys.defaultWatchFileKind = () => WatchFileKind.FixedChunkSizePolling;
|
||||
return sys;
|
||||
},
|
||||
changes: [
|
||||
{
|
||||
caption: "Make change to file but should detect as changed and schedule program update",
|
||||
// Make a change to file
|
||||
change: sys => sys.writeFile(commonFile1.path, "var zz30 = 100;"),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
},
|
||||
{
|
||||
caption: "Callbacks: queue and scheduled program update",
|
||||
change: noop,
|
||||
// Callbacks: scheduled program update and queue for the polling
|
||||
timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2),
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
describe("tsc-watch when watchDirectories implementation", () => {
|
||||
function verifyRenamingFileInSubFolder(subScenario: string, tscWatchDirectory: Tsc_WatchDirectory) {
|
||||
const projectFolder = "/a/username/project";
|
||||
|
||||
@ -180,21 +180,6 @@ namespace ts.server {
|
||||
const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys);
|
||||
const logger = createLogger();
|
||||
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
// on all os and with network mounted files.
|
||||
// For 90 referenced files, the average time to detect
|
||||
// changes is 2*msInterval (by default 5 seconds).
|
||||
// The overhead of this is .04 percent (1/2500) with
|
||||
// average pause of < 1 millisecond (and max
|
||||
// pause less than 1.5 milliseconds); question is
|
||||
// do we anticipate reference sets in the 100s and
|
||||
// do we care about waiting 10-20 seconds to detect
|
||||
// changes for large reference sets? If so, do we want
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
const pollingWatchedFileSet = createPollingWatchedFileSet();
|
||||
|
||||
const pending: Buffer[] = [];
|
||||
let canWrite = true;
|
||||
|
||||
@ -248,12 +233,20 @@ namespace ts.server {
|
||||
|
||||
// Override sys.write because fs.writeSync is not reliable on Node 4
|
||||
sys.write = (s: string) => writeMessage(sys.bufferFrom!(s, "utf8") as globalThis.Buffer);
|
||||
sys.watchFile = (fileName, callback) => {
|
||||
const watchedFile = pollingWatchedFileSet.addFile(fileName, callback);
|
||||
return {
|
||||
close: () => pollingWatchedFileSet.removeFile(watchedFile)
|
||||
};
|
||||
};
|
||||
// REVIEW: for now this implementation uses polling.
|
||||
// The advantage of polling is that it works reliably
|
||||
// on all os and with network mounted files.
|
||||
// For 90 referenced files, the average time to detect
|
||||
// changes is 2*msInterval (by default 5 seconds).
|
||||
// The overhead of this is .04 percent (1/2500) with
|
||||
// average pause of < 1 millisecond (and max
|
||||
// pause less than 1.5 milliseconds); question is
|
||||
// do we anticipate reference sets in the 100s and
|
||||
// do we care about waiting 10-20 seconds to detect
|
||||
// changes for large reference sets? If so, do we want
|
||||
// to increase the chunk size or decrease the interval
|
||||
// time dynamically to match the large reference set?
|
||||
sys.defaultWatchFileKind = () => WatchFileKind.FixedChunkSizePolling;
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
sys.setTimeout = setTimeout;
|
||||
@ -324,89 +317,6 @@ namespace ts.server {
|
||||
const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
|
||||
return new Logger(substitutedLogFileName!, envLogOptions.traceToConsole!, logVerbosity!); // TODO: GH#18217
|
||||
}
|
||||
// This places log file in the directory containing editorServices.js
|
||||
// TODO: check that this location is writable
|
||||
|
||||
// average async stat takes about 30 microseconds
|
||||
// set chunk size to do 30 files in < 1 millisecond
|
||||
function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) {
|
||||
const watchedFiles: WatchedFile[] = [];
|
||||
let nextFileToCheck = 0;
|
||||
return { getModifiedTime, poll, startWatchTimer, addFile, removeFile };
|
||||
|
||||
function getModifiedTime(fileName: string): Date {
|
||||
// Caller guarantees that `fileName` exists, so there'd be no benefit from throwIfNoEntry
|
||||
return fs.statSync(fileName).mtime;
|
||||
}
|
||||
|
||||
function poll(checkedIndex: number) {
|
||||
const watchedFile = watchedFiles[checkedIndex];
|
||||
if (!watchedFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.stat(watchedFile.fileName, (err, stats) => {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") {
|
||||
if (watchedFile.mtime.getTime() !== 0) {
|
||||
watchedFile.mtime = missingFileModifiedTime;
|
||||
watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Deleted);
|
||||
}
|
||||
}
|
||||
else {
|
||||
watchedFile.callback(watchedFile.fileName, FileWatcherEventKind.Changed);
|
||||
}
|
||||
}
|
||||
else {
|
||||
onWatchedFileStat(watchedFile, stats.mtime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this implementation uses polling and
|
||||
// stat due to inconsistencies of fs.watch
|
||||
// and efficiency of stat on modern filesystems
|
||||
function startWatchTimer() {
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
setInterval(() => {
|
||||
let count = 0;
|
||||
let nextToCheck = nextFileToCheck;
|
||||
let firstCheck = -1;
|
||||
while ((count < chunkSize) && (nextToCheck !== firstCheck)) {
|
||||
poll(nextToCheck);
|
||||
if (firstCheck < 0) {
|
||||
firstCheck = nextToCheck;
|
||||
}
|
||||
nextToCheck++;
|
||||
if (nextToCheck === watchedFiles.length) {
|
||||
nextToCheck = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
nextFileToCheck = nextToCheck;
|
||||
}, interval);
|
||||
}
|
||||
|
||||
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
|
||||
const file: WatchedFile = {
|
||||
fileName,
|
||||
callback,
|
||||
mtime: sys.fileExists(fileName)
|
||||
? getModifiedTime(fileName)
|
||||
: missingFileModifiedTime // Any subsequent modification will occur after this time
|
||||
};
|
||||
|
||||
watchedFiles.push(file);
|
||||
if (watchedFiles.length === 1) {
|
||||
startWatchTimer();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
function removeFile(file: WatchedFile) {
|
||||
unorderedRemoveItem(watchedFiles, file);
|
||||
}
|
||||
}
|
||||
|
||||
function writeMessage(buf: Buffer) {
|
||||
if (!canWrite) {
|
||||
|
||||
@ -2775,18 +2775,21 @@ declare namespace ts {
|
||||
FixedPollingInterval = 0,
|
||||
PriorityPollingInterval = 1,
|
||||
DynamicPriorityPolling = 2,
|
||||
UseFsEvents = 3,
|
||||
UseFsEventsOnParentDirectory = 4
|
||||
FixedChunkSizePolling = 3,
|
||||
UseFsEvents = 4,
|
||||
UseFsEventsOnParentDirectory = 5
|
||||
}
|
||||
export enum WatchDirectoryKind {
|
||||
UseFsEvents = 0,
|
||||
FixedPollingInterval = 1,
|
||||
DynamicPriorityPolling = 2
|
||||
DynamicPriorityPolling = 2,
|
||||
FixedChunkSizePolling = 3
|
||||
}
|
||||
export enum PollingWatchKind {
|
||||
FixedInterval = 0,
|
||||
PriorityInterval = 1,
|
||||
DynamicPriority = 2
|
||||
DynamicPriority = 2,
|
||||
FixedChunkSize = 3
|
||||
}
|
||||
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
|
||||
export interface CompilerOptions {
|
||||
@ -7685,18 +7688,21 @@ declare namespace ts.server.protocol {
|
||||
FixedPollingInterval = "FixedPollingInterval",
|
||||
PriorityPollingInterval = "PriorityPollingInterval",
|
||||
DynamicPriorityPolling = "DynamicPriorityPolling",
|
||||
FixedChunkSizePolling = "FixedChunkSizePolling",
|
||||
UseFsEvents = "UseFsEvents",
|
||||
UseFsEventsOnParentDirectory = "UseFsEventsOnParentDirectory"
|
||||
}
|
||||
enum WatchDirectoryKind {
|
||||
UseFsEvents = "UseFsEvents",
|
||||
FixedPollingInterval = "FixedPollingInterval",
|
||||
DynamicPriorityPolling = "DynamicPriorityPolling"
|
||||
DynamicPriorityPolling = "DynamicPriorityPolling",
|
||||
FixedChunkSizePolling = "FixedChunkSizePolling"
|
||||
}
|
||||
enum PollingWatchKind {
|
||||
FixedInterval = "FixedInterval",
|
||||
PriorityInterval = "PriorityInterval",
|
||||
DynamicPriority = "DynamicPriority"
|
||||
DynamicPriority = "DynamicPriority",
|
||||
FixedChunkSize = "FixedChunkSize"
|
||||
}
|
||||
interface WatchOptions {
|
||||
watchFile?: WatchFileKind | ts.WatchFileKind;
|
||||
|
||||
11
tests/baselines/reference/api/typescript.d.ts
vendored
11
tests/baselines/reference/api/typescript.d.ts
vendored
@ -2775,18 +2775,21 @@ declare namespace ts {
|
||||
FixedPollingInterval = 0,
|
||||
PriorityPollingInterval = 1,
|
||||
DynamicPriorityPolling = 2,
|
||||
UseFsEvents = 3,
|
||||
UseFsEventsOnParentDirectory = 4
|
||||
FixedChunkSizePolling = 3,
|
||||
UseFsEvents = 4,
|
||||
UseFsEventsOnParentDirectory = 5
|
||||
}
|
||||
export enum WatchDirectoryKind {
|
||||
UseFsEvents = 0,
|
||||
FixedPollingInterval = 1,
|
||||
DynamicPriorityPolling = 2
|
||||
DynamicPriorityPolling = 2,
|
||||
FixedChunkSizePolling = 3
|
||||
}
|
||||
export enum PollingWatchKind {
|
||||
FixedInterval = 0,
|
||||
PriorityInterval = 1,
|
||||
DynamicPriority = 2
|
||||
DynamicPriority = 2,
|
||||
FixedChunkSize = 3
|
||||
}
|
||||
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
|
||||
export interface CompilerOptions {
|
||||
|
||||
@ -0,0 +1,131 @@
|
||||
Input::
|
||||
//// [/a/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
|
||||
//// [/a/b/commonFile1.ts]
|
||||
let x = 1
|
||||
|
||||
//// [/a/b/commonFile2.ts]
|
||||
let y = 1
|
||||
|
||||
//// [/a/b/tsconfig.json]
|
||||
{}
|
||||
|
||||
|
||||
/a/lib/tsc.js -w -p /a/b/tsconfig.json
|
||||
Output::
|
||||
>> Screen clear
|
||||
[[90m12:00:17 AM[0m] Starting compilation in watch mode...
|
||||
|
||||
[[90m12:00:22 AM[0m] Found 0 errors. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"]
|
||||
Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"}
|
||||
Program structureReused: Not
|
||||
Program files::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
Semantic diagnostics in builder refreshed for::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/a/b/commonFile1.js]
|
||||
var x = 1;
|
||||
|
||||
|
||||
//// [/a/b/commonFile2.js]
|
||||
var y = 1;
|
||||
|
||||
|
||||
|
||||
Change:: Make change to file but should detect as changed and schedule program update
|
||||
|
||||
Input::
|
||||
//// [/a/b/commonFile1.ts]
|
||||
var zz30 = 100;
|
||||
|
||||
|
||||
Output::
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
|
||||
Change:: Callbacks: queue and scheduled program update
|
||||
|
||||
Input::
|
||||
|
||||
Output::
|
||||
>> Screen clear
|
||||
[[90m12:00:26 AM[0m] File change detected. Starting incremental compilation...
|
||||
|
||||
[[90m12:00:33 AM[0m] Found 0 errors. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"]
|
||||
Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"}
|
||||
Program structureReused: Completely
|
||||
Program files::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
Semantic diagnostics in builder refreshed for::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/a/b/commonFile1.js]
|
||||
var zz30 = 100;
|
||||
|
||||
|
||||
//// [/a/b/commonFile2.js] file written with same contents
|
||||
@ -0,0 +1,169 @@
|
||||
Input::
|
||||
//// [/a/lib/lib.d.ts]
|
||||
/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
interface CallableFunction {}
|
||||
interface NewableFunction {}
|
||||
interface IArguments {}
|
||||
interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
|
||||
//// [/a/b/commonFile1.ts]
|
||||
let x = 1
|
||||
|
||||
//// [/a/b/commonFile2.ts]
|
||||
let y = 1
|
||||
|
||||
//// [/a/b/tsconfig.json]
|
||||
{"watchOptions":{"watchFile":"FixedChunkSizePolling"}}
|
||||
|
||||
|
||||
/a/lib/tsc.js -w -p /a/b/tsconfig.json
|
||||
Output::
|
||||
>> Screen clear
|
||||
[[90m12:00:17 AM[0m] Starting compilation in watch mode...
|
||||
|
||||
[[90m12:00:22 AM[0m] Found 0 errors. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"]
|
||||
Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"}
|
||||
Program structureReused: Not
|
||||
Program files::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
Semantic diagnostics in builder refreshed for::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/a/b/commonFile1.js]
|
||||
var x = 1;
|
||||
|
||||
|
||||
//// [/a/b/commonFile2.js]
|
||||
var y = 1;
|
||||
|
||||
|
||||
|
||||
Change:: The timeout is to check the status of all files
|
||||
|
||||
Input::
|
||||
|
||||
Output::
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
|
||||
Change:: Make change to file but should detect as changed and schedule program update
|
||||
|
||||
Input::
|
||||
//// [/a/b/commonFile1.ts]
|
||||
var zz30 = 100;
|
||||
|
||||
|
||||
Output::
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
|
||||
Change:: Callbacks: queue and scheduled program update
|
||||
|
||||
Input::
|
||||
|
||||
Output::
|
||||
>> Screen clear
|
||||
[[90m12:00:26 AM[0m] File change detected. Starting incremental compilation...
|
||||
|
||||
[[90m12:00:33 AM[0m] Found 0 errors. Watching for file changes.
|
||||
|
||||
|
||||
|
||||
Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"]
|
||||
Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"}
|
||||
Program structureReused: Completely
|
||||
Program files::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
Semantic diagnostics in builder refreshed for::
|
||||
/a/lib/lib.d.ts
|
||||
/a/b/commonFile1.ts
|
||||
/a/b/commonFile2.ts
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
//// [/a/b/commonFile1.js]
|
||||
var zz30 = 100;
|
||||
|
||||
|
||||
//// [/a/b/commonFile2.js] file written with same contents
|
||||
|
||||
Change:: The timeout is to check the status of all files
|
||||
|
||||
Input::
|
||||
|
||||
Output::
|
||||
|
||||
WatchedFiles::
|
||||
|
||||
FsWatches::
|
||||
|
||||
FsWatchesRecursive::
|
||||
/a/b/node_modules/@types:
|
||||
{"directoryName":"/a/b/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
/a/b:
|
||||
{"directoryName":"/a/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}}
|
||||
|
||||
exitCode:: ExitStatus.undefined
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user