Use watch factory instead of direct host functions in tsbuild to provide detailed information on watch invokations

This commit is contained in:
Sheetal Nandi 2018-12-14 15:13:19 -08:00
parent b8def16e92
commit 0cabb00b34
6 changed files with 92 additions and 54 deletions

View File

@ -443,6 +443,7 @@ namespace ts {
let nextProjectToBuild = 0;
let timerToBuildInvalidatedProject: any;
let reportFileChangeDetected = false;
const { watchFile, watchFilePath, watchDirectory } = createWatchFactory<ResolvedConfigFileName>(host, options);
// Watches for the solution
const allWatchedWildcardDirectories = createFileMap<Map<WildcardDirectoryWatcher>>(toPath);
@ -542,9 +543,16 @@ namespace ts {
function watchConfigFile(resolved: ResolvedConfigFileName) {
if (options.watch && !allWatchedConfigFiles.hasKey(resolved)) {
allWatchedConfigFiles.setValue(resolved, hostWithWatch.watchFile(resolved, () => {
allWatchedConfigFiles.setValue(resolved, watchFile(
hostWithWatch,
resolved,
() => {
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full);
}));
},
PollingInterval.High,
WatchType.ConfigFile,
resolved
));
}
}
@ -554,20 +562,27 @@ namespace ts {
getOrCreateValueMapFromConfigFileMap(allWatchedWildcardDirectories, resolved),
createMapFromTemplate(parsed.configFileSpecs!.wildcardDirectories),
(dir, flags) => {
return hostWithWatch.watchDirectory(dir, fileOrDirectory => {
const fileOrDirectoryPath = toPath(fileOrDirectory);
if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, parsed.options)) {
// writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
return;
}
return watchDirectory(
hostWithWatch,
dir,
fileOrDirectory => {
const fileOrDirectoryPath = toPath(fileOrDirectory);
if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, parsed.options)) {
// writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
return;
}
if (isOutputFile(fileOrDirectory, parsed)) {
// writeLog(`${fileOrDirectory} is output file`);
return;
}
if (isOutputFile(fileOrDirectory, parsed)) {
// writeLog(`${fileOrDirectory} is output file`);
return;
}
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial);
}, !!(flags & WatchDirectoryFlags.Recursive));
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial);
},
flags,
WatchType.WildcardDirectory,
resolved
);
}
);
}
@ -578,9 +593,15 @@ namespace ts {
getOrCreateValueMapFromConfigFileMap(allWatchedInputFiles, resolved),
arrayToMap(parsed.fileNames, toPath),
{
createNewValue: (_key, input) => hostWithWatch.watchFile(input, () => {
invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None);
}),
createNewValue: (path, input) => watchFilePath(
hostWithWatch,
input,
() => invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None),
PollingInterval.Low,
path as Path,
WatchType.SourceFile,
resolved
),
onDeleteValue: closeFileWatcher,
}
);

View File

@ -194,6 +194,30 @@ namespace ts {
};
}
export const enum WatchType {
ConfigFile = "Config file",
SourceFile = "Source file",
MissingFile = "Missing file",
WildcardDirectory = "Wild card directory",
FailedLookupLocations = "Failed Lookup Locations",
TypeRoots = "Type roots"
}
interface WatchFactory<X, Y= undefined> extends ts.WatchFactory<X, Y> {
watchLogLevel: WatchLogLevel;
writeLog: (s: string) => void;
}
export function createWatchFactory<Y = undefined>(host: { trace?(s: string): void; }, options: { extendedDiagnostics?: boolean; diagnostics?: boolean; }) {
const watchLogLevel = host.trace ? options.extendedDiagnostics ? WatchLogLevel.Verbose :
options.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => host.trace!(s)) : noop;
const result = getWatchFactory<WatchType, Y>(watchLogLevel, writeLog) as WatchFactory<WatchType, Y>;
result.watchLogLevel = watchLogLevel;
result.writeLog = writeLog;
return result;
}
/**
* Creates the watch compiler host that can be extended with config file or root file names and options host
*/
@ -224,7 +248,7 @@ namespace ts {
watchDirectory,
setTimeout,
clearTimeout,
trace: s => system.write(s),
trace: s => system.write(s + system.newLine),
onWatchStatusChange,
createDirectory: path => system.createDirectory(path),
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
@ -517,17 +541,12 @@ namespace ts {
newLine = updateNewLine();
}
const trace = host.trace && ((s: string) => { host.trace!(s + newLine); });
const watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? WatchLogLevel.Verbose :
compilerOptions.diagnostics ? WatchLogLevel.TriggerOnly : WatchLogLevel.None : WatchLogLevel.None;
const writeLog: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? trace! : noop; // TODO: GH#18217
const { watchFile, watchFilePath, watchDirectory } = getWatchFactory<string>(watchLogLevel, writeLog);
const { watchFile, watchFilePath, watchDirectory, watchLogLevel, writeLog } = createWatchFactory<string>(host, compilerOptions);
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`);
if (configFileName) {
watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, "Config file");
watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, WatchType.ConfigFile);
}
const compilerHost: CompilerHost & ResolutionCacheHost = {
@ -543,7 +562,7 @@ namespace ts {
getNewLine: () => newLine,
fileExists,
readFile,
trace,
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)),
@ -553,8 +572,8 @@ namespace ts {
// Members for ResolutionCacheHost
toPath,
getCompilationSettings: () => compilerOptions,
watchDirectoryOfFailedLookupLocation: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, "Failed Lookup Locations"),
watchTypeRootsDirectory: (dir, cb, flags) => watchDirectory(host, dir, cb, flags, "Type roots"),
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: () => {
@ -719,7 +738,7 @@ namespace ts {
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
sourceFile.version = hostSourceFile.version.toString();
if (!(hostSourceFile as FilePresentOnHost).fileWatcher) {
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, "Source file");
(hostSourceFile as FilePresentOnHost).fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
}
}
else {
@ -733,7 +752,7 @@ namespace ts {
else {
if (sourceFile) {
sourceFile.version = initialVersion.toString();
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, "Source file");
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
sourceFilesCache.set(path, { sourceFile, version: initialVersion, fileWatcher });
}
else {
@ -907,7 +926,7 @@ namespace ts {
}
function watchMissingFilePath(missingFilePath: Path) {
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, "Missing file");
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, WatchType.MissingFile);
}
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
@ -971,7 +990,7 @@ namespace ts {
}
},
flags,
"Wild card directories"
WatchType.WildcardDirectory
);
}

View File

@ -343,10 +343,10 @@ namespace ts {
export interface WatchDirectoryHost {
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
}
export type WatchFile<X, Y> = (host: WatchFileHost, file: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchFile<X, Y> = (host: WatchFileHost, 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: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1?: X, detailInfo2?: Y) => FileWatcher;
export type WatchFilePath<X, Y> = (host: WatchFileHost, file: string, callback: FilePathWatcherCallback, pollingInterval: PollingInterval, path: Path, detailInfo1: X, detailInfo2?: Y) => FileWatcher;
export type WatchDirectory<X, Y> = (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags, detailInfo1: X, detailInfo2?: Y) => FileWatcher;
export interface WatchFactory<X, Y> {
watchFile: WatchFile<X, Y>;
@ -444,7 +444,7 @@ namespace ts {
}
function getWatchInfo<T, X, Y>(file: string, flags: T, detailInfo1: X, detailInfo2: Y | undefined, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined) {
return `WatchInfo: ${file} ${flags} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : detailInfo1}`;
return `WatchInfo: ${file} ${flags} ${getDetailWatchInfo ? getDetailWatchInfo(detailInfo1, detailInfo2) : detailInfo2 === undefined ? detailInfo1 : `${detailInfo1} ${detailInfo2}`}`;
}
export function closeFileWatcherOf<T extends { watcher: FileWatcher; }>(objWithWatcher: T) {

View File

@ -332,19 +332,6 @@ namespace ts.server {
}
}
/* @internal */
export const enum WatchType {
ConfigFilePath = "Config file for the program",
MissingFilePath = "Missing file from program",
WildcardDirectories = "Wild card directory",
ClosedScriptInfo = "Closed Script info",
ConfigFileForInferredRoot = "Config file for the inferred project root",
FailedLookupLocation = "Directory of Failed lookup locations in module resolution",
TypeRoots = "Type root directory",
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
MissingSourceMapFile = "Missing source map file"
}
const enum ConfigFileWatcherStatus {
ReloadingFiles = "Reloading configured projects for files",
ReloadingInferredRootFiles = "Reloading configured projects for only inferred root files",
@ -1035,7 +1022,7 @@ namespace ts.server {
}
},
flags,
WatchType.WildcardDirectories,
WatchType.WildcardDirectory,
project
);
}
@ -1338,7 +1325,7 @@ namespace ts.server {
watches.push(WatchType.ConfigFileForInferredRoot);
}
if (this.configuredProjects.has(canonicalConfigFilePath)) {
watches.push(WatchType.ConfigFilePath);
watches.push(WatchType.ConfigFile);
}
this.logger.info(`ConfigFilePresence:: Current Watches: ${watches}:: File: ${configFileName} Currently impacted open files: RootsOfInferredProjects: ${inferredRoots} OtherOpenFiles: ${otherFiles} Status: ${status}`);
}
@ -1705,7 +1692,7 @@ namespace ts.server {
configFileName,
(_fileName, eventKind) => this.onConfigChangedForConfiguredProject(project, eventKind),
PollingInterval.High,
WatchType.ConfigFilePath,
WatchType.ConfigFile,
project
);
this.configuredProjects.set(project.canonicalConfigFilePath, project);

View File

@ -428,7 +428,7 @@ namespace ts.server {
directory,
cb,
flags,
WatchType.FailedLookupLocation,
WatchType.FailedLookupLocations,
this
);
}
@ -989,7 +989,7 @@ namespace ts.server {
}
},
PollingInterval.Medium,
WatchType.MissingFilePath,
WatchType.MissingFile,
this
);
return fileWatcher;

View File

@ -217,3 +217,14 @@ namespace ts.server {
return indentStr + JSON.stringify(json);
}
}
/* @internal */
namespace ts {
// Additional tsserver specific watch information
export const enum WatchType {
ClosedScriptInfo = "Closed Script info",
ConfigFileForInferredRoot = "Config file for the inferred project root",
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
MissingSourceMapFile = "Missing source map file",
}
}