mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-23 17:30:04 -05:00
More work based on feedback
This commit is contained in:
@@ -2631,12 +2631,16 @@ namespace ts {
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
}
|
||||
|
||||
export interface CachedHost extends PartialSystem {
|
||||
addOrDeleteFileOrFolder(fileOrFolder: string): void;
|
||||
export interface CachedHost {
|
||||
addOrDeleteFileOrFolder(fileOrFolder: string, fileOrFolderPath: Path): void;
|
||||
addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void;
|
||||
clearCache(): void;
|
||||
}
|
||||
|
||||
export function createCachedHost(host: HostForCaching): CachedHost {
|
||||
export interface CachedPartialSystem extends PartialSystem, CachedHost {
|
||||
}
|
||||
|
||||
export function createCachedPartialSystem(host: HostForCaching): CachedPartialSystem {
|
||||
const cachedReadDirectoryResult = createMap<FileSystemEntries>();
|
||||
const getCurrentDirectory = memoize(() => host.getCurrentDirectory());
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
@@ -2649,6 +2653,7 @@ namespace ts {
|
||||
getDirectories,
|
||||
readDirectory,
|
||||
addOrDeleteFileOrFolder,
|
||||
addOrDeleteFile,
|
||||
clearCache
|
||||
};
|
||||
|
||||
@@ -2656,33 +2661,46 @@ namespace ts {
|
||||
return ts.toPath(fileName, getCurrentDirectory(), getCanonicalFileName);
|
||||
}
|
||||
|
||||
function getFileSystemEntries(rootDir: string) {
|
||||
const path = toPath(rootDir);
|
||||
const cachedResult = cachedReadDirectoryResult.get(path);
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
function getCachedFileSystemEntries(rootDirPath: Path): FileSystemEntries | undefined {
|
||||
return cachedReadDirectoryResult.get(rootDirPath);
|
||||
}
|
||||
|
||||
function getCachedFileSystemEntriesForBaseDir(path: Path): FileSystemEntries | undefined {
|
||||
return getCachedFileSystemEntries(getDirectoryPath(path));
|
||||
}
|
||||
|
||||
function getBaseNameOfFileName(fileName: string) {
|
||||
return getBaseFileName(normalizePath(fileName));
|
||||
}
|
||||
|
||||
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
|
||||
const resultFromHost: FileSystemEntries = {
|
||||
files: host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]) || [],
|
||||
directories: host.getDirectories(rootDir) || []
|
||||
};
|
||||
|
||||
cachedReadDirectoryResult.set(path, resultFromHost);
|
||||
cachedReadDirectoryResult.set(rootDirPath, resultFromHost);
|
||||
return resultFromHost;
|
||||
}
|
||||
|
||||
function canWorkWithCacheForDir(rootDir: string) {
|
||||
// Some of the hosts might not be able to handle read directory or getDirectories
|
||||
const path = toPath(rootDir);
|
||||
if (cachedReadDirectoryResult.get(path)) {
|
||||
return true;
|
||||
/**
|
||||
* If the readDirectory result was already cached, it returns that
|
||||
* Otherwise gets result from host and caches it.
|
||||
* The host request is done under try catch block to avoid caching incorrect result
|
||||
*/
|
||||
function tryReadDirectory(rootDir: string, rootDirPath: Path): FileSystemEntries | undefined {
|
||||
const cachedResult = getCachedFileSystemEntries(rootDirPath);
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
try {
|
||||
return getFileSystemEntries(rootDir);
|
||||
return createCachedFileSystemEntries(rootDir, rootDirPath);
|
||||
}
|
||||
catch (_e) {
|
||||
return false;
|
||||
// If there is exception to read directories, dont cache the result and direct the calls to host
|
||||
Debug.assert(!cachedReadDirectoryResult.has(rootDirPath));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2708,19 +2726,18 @@ namespace ts {
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
|
||||
const path = toPath(fileName);
|
||||
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
|
||||
const baseFileName = getBaseFileName(normalizePath(fileName));
|
||||
const result = getCachedFileSystemEntriesForBaseDir(path);
|
||||
if (result) {
|
||||
result.files = updateFileSystemEntry(result.files, baseFileName, /*isValid*/ true);
|
||||
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
|
||||
}
|
||||
return host.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
function fileExists(fileName: string): boolean {
|
||||
const path = toPath(fileName);
|
||||
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
|
||||
const baseName = getBaseFileName(normalizePath(fileName));
|
||||
return (result && hasEntry(result.files, baseName)) || host.fileExists(fileName);
|
||||
const result = getCachedFileSystemEntriesForBaseDir(path);
|
||||
return (result && hasEntry(result.files, getBaseNameOfFileName(fileName))) ||
|
||||
host.fileExists(fileName);
|
||||
}
|
||||
|
||||
function directoryExists(dirPath: string): boolean {
|
||||
@@ -2730,8 +2747,8 @@ namespace ts {
|
||||
|
||||
function createDirectory(dirPath: string) {
|
||||
const path = toPath(dirPath);
|
||||
const result = cachedReadDirectoryResult.get(getDirectoryPath(path));
|
||||
const baseFileName = getBaseFileName(path);
|
||||
const result = getCachedFileSystemEntriesForBaseDir(path);
|
||||
const baseFileName = getBaseNameOfFileName(dirPath);
|
||||
if (result) {
|
||||
result.directories = updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
|
||||
}
|
||||
@@ -2739,41 +2756,68 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDirectories(rootDir: string): string[] {
|
||||
if (canWorkWithCacheForDir(rootDir)) {
|
||||
return getFileSystemEntries(rootDir).directories.slice();
|
||||
const rootDirPath = toPath(rootDir);
|
||||
const result = tryReadDirectory(rootDir, rootDirPath);
|
||||
if (result) {
|
||||
return result.directories.slice();
|
||||
}
|
||||
return host.getDirectories(rootDir);
|
||||
}
|
||||
|
||||
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
if (canWorkWithCacheForDir(rootDir)) {
|
||||
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, path => getFileSystemEntries(path));
|
||||
const rootDirPath = toPath(rootDir);
|
||||
const result = tryReadDirectory(rootDir, rootDirPath);
|
||||
if (result) {
|
||||
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, getFileSystemEntries);
|
||||
}
|
||||
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
|
||||
|
||||
function getFileSystemEntries(dir: string) {
|
||||
const path = toPath(dir);
|
||||
if (path === rootDirPath) {
|
||||
return result;
|
||||
}
|
||||
return getCachedFileSystemEntries(path) || createCachedFileSystemEntries(dir, path);
|
||||
}
|
||||
}
|
||||
|
||||
function addOrDeleteFileOrFolder(fileOrFolder: string) {
|
||||
const path = toPath(fileOrFolder);
|
||||
const existingResult = cachedReadDirectoryResult.get(path);
|
||||
function addOrDeleteFileOrFolder(fileOrFolder: string, fileOrFolderPath: Path) {
|
||||
const existingResult = getCachedFileSystemEntries(fileOrFolderPath);
|
||||
if (existingResult) {
|
||||
// This was a folder already present, remove it if this doesnt exist any more
|
||||
if (!host.directoryExists(fileOrFolder)) {
|
||||
cachedReadDirectoryResult.delete(path);
|
||||
cachedReadDirectoryResult.delete(fileOrFolderPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This was earlier a file (hence not in cached directory contents)
|
||||
// or we never cached the directory containing it
|
||||
const parentResult = cachedReadDirectoryResult.get(getDirectoryPath(path));
|
||||
const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrFolderPath);
|
||||
if (parentResult) {
|
||||
const baseName = getBaseFileName(fileOrFolder);
|
||||
const baseName = getBaseNameOfFileName(fileOrFolder);
|
||||
if (parentResult) {
|
||||
parentResult.files = updateFileSystemEntry(parentResult.files, baseName, host.fileExists(path));
|
||||
parentResult.directories = updateFileSystemEntry(parentResult.directories, baseName, host.directoryExists(path));
|
||||
updateFilesOfFileSystemEntry(parentResult, baseName, host.fileExists(fileOrFolderPath));
|
||||
parentResult.directories = updateFileSystemEntry(parentResult.directories, baseName, host.directoryExists(fileOrFolderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind) {
|
||||
if (eventKind === FileWatcherEventKind.Changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath);
|
||||
if (parentResult) {
|
||||
updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFilesOfFileSystemEntry(parentResult: FileSystemEntries, baseName: string, fileExists: boolean) {
|
||||
parentResult.files = updateFileSystemEntry(parentResult.files, baseName, fileExists);
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
cachedReadDirectoryResult.clear();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace ts {
|
||||
export function createResolutionCache(
|
||||
toPath: (fileName: string) => Path,
|
||||
getCompilerOptions: () => CompilerOptions,
|
||||
watchForFailedLookupLocation: (failedLookupLocation: string, containingFile: string, name: string) => FileWatcher,
|
||||
watchForFailedLookupLocation: (failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) => FileWatcher,
|
||||
log: (s: string) => void,
|
||||
resolveWithGlobalCache?: ResolverWithGlobalCache): ResolutionCache {
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
log(`Watcher: FailedLookupLocations: Status: new watch: Location: ${failedLookupLocation}, containingFile: ${containingFile}, name: ${name}`);
|
||||
const fileWatcher = watchForFailedLookupLocation(failedLookupLocation, containingFile, name);
|
||||
const fileWatcher = watchForFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, containingFile, name);
|
||||
failedLookupLocationsWatches.set(failedLookupLocationPath, { fileWatcher, refCount: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ namespace ts {
|
||||
function onSourceFileChange(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
|
||||
writeLog(`Source file path : ${path} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName}`);
|
||||
|
||||
updateCachedSystem(fileName, path);
|
||||
updateCachedSystemWithFile(fileName, path, eventKind);
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
if (hostSourceFile) {
|
||||
// Update the cache
|
||||
@@ -547,21 +547,19 @@ namespace ts {
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateCachedSystem(fileName: string, path: Path) {
|
||||
function updateCachedSystemWithFile(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
|
||||
if (configFileName) {
|
||||
const absoluteNormalizedPath = getNormalizedAbsolutePath(fileName, getDirectoryPath(path));
|
||||
(host as CachedSystem).addOrDeleteFileOrFolder(normalizePath(absoluteNormalizedPath));
|
||||
(host as CachedSystem).addOrDeleteFile(fileName, path, eventKind);
|
||||
}
|
||||
}
|
||||
|
||||
function watchFailedLookupLocation(failedLookupLocation: string, containingFile: string, name: string) {
|
||||
return host.watchFile(failedLookupLocation, (fileName, eventKind) => onFailedLookupLocationChange(fileName, eventKind, failedLookupLocation, containingFile, name));
|
||||
function watchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
|
||||
return host.watchFile(failedLookupLocation, (fileName, eventKind) => onFailedLookupLocationChange(fileName, eventKind, failedLookupLocation, failedLookupLocationPath, containingFile, name));
|
||||
}
|
||||
|
||||
function onFailedLookupLocationChange(fileName: string, eventKind: FileWatcherEventKind, failedLookupLocation: string, containingFile: string, name: string) {
|
||||
function onFailedLookupLocationChange(fileName: string, eventKind: FileWatcherEventKind, failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
|
||||
writeLog(`Failed lookup location : ${failedLookupLocation} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName} containingFile: ${containingFile}, name: ${name}`);
|
||||
const path = toPath(failedLookupLocation);
|
||||
updateCachedSystem(failedLookupLocation, path);
|
||||
updateCachedSystemWithFile(fileName, failedLookupLocationPath, eventKind);
|
||||
resolutionCache.invalidateResolutionOfChangedFailedLookupLocation(failedLookupLocation);
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
@@ -574,14 +572,14 @@ namespace ts {
|
||||
fileWatcher.close();
|
||||
}
|
||||
|
||||
function onMissingFileChange(filename: string, missingFilePath: Path, eventKind: FileWatcherEventKind) {
|
||||
writeLog(`Missing file path : ${missingFilePath} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${filename}`);
|
||||
function onMissingFileChange(fileName: string, missingFilePath: Path, eventKind: FileWatcherEventKind) {
|
||||
writeLog(`Missing file path : ${missingFilePath} changed: ${FileWatcherEventKind[eventKind]}, fileName: ${fileName}`);
|
||||
updateCachedSystemWithFile(fileName, missingFilePath, eventKind);
|
||||
|
||||
if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) {
|
||||
closeMissingFilePathWatcher(missingFilePath, missingFilesMap.get(missingFilePath));
|
||||
missingFilesMap.delete(missingFilePath);
|
||||
|
||||
updateCachedSystem(filename, missingFilePath);
|
||||
|
||||
// Delete the entry in the source files cache so that new source file is created
|
||||
removeSourceFile(missingFilePath);
|
||||
|
||||
@@ -600,8 +598,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function watchWildCardDirectory(directory: string, flags: WatchDirectoryFlags) {
|
||||
return host.watchDirectory(directory, fileName =>
|
||||
onFileAddOrRemoveInWatchedDirectory(getNormalizedAbsolutePath(fileName, directory)),
|
||||
return host.watchDirectory(directory, fileOrFolder =>
|
||||
onFileAddOrRemoveInWatchedDirectory(getNormalizedAbsolutePath(fileOrFolder, directory)),
|
||||
(flags & WatchDirectoryFlags.Recursive) !== 0);
|
||||
}
|
||||
|
||||
@@ -609,24 +607,24 @@ namespace ts {
|
||||
watcher.close();
|
||||
}
|
||||
|
||||
function onFileAddOrRemoveInWatchedDirectory(fileName: string) {
|
||||
function onFileAddOrRemoveInWatchedDirectory(fileOrFolder: string) {
|
||||
Debug.assert(!!configFileName);
|
||||
|
||||
const path = toPath(fileName);
|
||||
const fileOrFolderPath = toPath(fileOrFolder);
|
||||
|
||||
// Since the file existance changed, update the sourceFiles cache
|
||||
updateCachedSystem(fileName, path);
|
||||
removeSourceFile(path);
|
||||
(host as CachedSystem).addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath);
|
||||
removeSourceFile(fileOrFolderPath);
|
||||
|
||||
// If a change was made inside "folder/file", node will trigger the callback twice:
|
||||
// one with the fileName being "folder/file", and the other one with "folder".
|
||||
// We don't respond to the second one.
|
||||
if (fileName && !isSupportedSourceFileName(fileName, compilerOptions)) {
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileName}`);
|
||||
if (fileOrFolder && !isSupportedSourceFileName(fileOrFolder, compilerOptions)) {
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrFolder}`);
|
||||
return;
|
||||
}
|
||||
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of supported extension: ${fileName}`);
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of supported extension: ${fileOrFolder}`);
|
||||
|
||||
// Reload is pending, do the reload
|
||||
if (!needsReload) {
|
||||
@@ -658,9 +656,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
interface CachedSystem extends System {
|
||||
addOrDeleteFileOrFolder(fileOrFolder: string): void;
|
||||
clearCache(): void;
|
||||
interface CachedSystem extends System, CachedHost {
|
||||
}
|
||||
|
||||
function createCachedSystem(host: System): CachedSystem {
|
||||
@@ -675,7 +671,7 @@ namespace ts {
|
||||
const setTimeout = host.setTimeout ? (callback: (...args: any[]) => void, ms: number, ...args: any[]) => host.setTimeout(callback, ms, ...args) : undefined;
|
||||
const clearTimeout = host.clearTimeout ? (timeoutId: any) => host.clearTimeout(timeoutId) : undefined;
|
||||
|
||||
const cachedHost = createCachedHost(host);
|
||||
const cachedPartialSystem = createCachedPartialSystem(host);
|
||||
return {
|
||||
args: host.args,
|
||||
newLine: host.newLine,
|
||||
@@ -683,17 +679,17 @@ namespace ts {
|
||||
write: s => host.write(s),
|
||||
readFile: (path, encoding?) => host.readFile(path, encoding),
|
||||
getFileSize,
|
||||
writeFile: (fileName, data, writeByteOrderMark?) => cachedHost.writeFile(fileName, data, writeByteOrderMark),
|
||||
writeFile: (fileName, data, writeByteOrderMark?) => cachedPartialSystem.writeFile(fileName, data, writeByteOrderMark),
|
||||
watchFile,
|
||||
watchDirectory,
|
||||
resolvePath: path => host.resolvePath(path),
|
||||
fileExists: fileName => cachedHost.fileExists(fileName),
|
||||
directoryExists: dir => cachedHost.directoryExists(dir),
|
||||
createDirectory: dir => cachedHost.createDirectory(dir),
|
||||
fileExists: fileName => cachedPartialSystem.fileExists(fileName),
|
||||
directoryExists: dir => cachedPartialSystem.directoryExists(dir),
|
||||
createDirectory: dir => cachedPartialSystem.createDirectory(dir),
|
||||
getExecutingFilePath: () => host.getExecutingFilePath(),
|
||||
getCurrentDirectory: () => cachedHost.getCurrentDirectory(),
|
||||
getDirectories: dir => cachedHost.getDirectories(dir),
|
||||
readDirectory: (path, extensions, excludes, includes, depth) => cachedHost.readDirectory(path, extensions, excludes, includes, depth),
|
||||
getCurrentDirectory: () => cachedPartialSystem.getCurrentDirectory(),
|
||||
getDirectories: dir => cachedPartialSystem.getDirectories(dir),
|
||||
readDirectory: (path, extensions, excludes, includes, depth) => cachedPartialSystem.readDirectory(path, extensions, excludes, includes, depth),
|
||||
getModifiedTime,
|
||||
createHash,
|
||||
getMemoryUsage,
|
||||
@@ -704,8 +700,9 @@ namespace ts {
|
||||
debugMode: host.debugMode,
|
||||
setTimeout,
|
||||
clearTimeout,
|
||||
addOrDeleteFileOrFolder: fileOrFolder => cachedHost.addOrDeleteFileOrFolder(fileOrFolder),
|
||||
clearCache: () => cachedHost.clearCache()
|
||||
addOrDeleteFileOrFolder: (fileOrFolder, fileOrFolderPath) => cachedPartialSystem.addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath),
|
||||
addOrDeleteFile: (file, filePath, eventKind) => cachedPartialSystem.addOrDeleteFile(file, filePath, eventKind),
|
||||
clearCache: () => cachedPartialSystem.clearCache()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,8 +695,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
onTypeRootFileChanged(project: ConfiguredProject, fileName: NormalizedPath) {
|
||||
project.getCachedServerHost().addOrDeleteFileOrFolder(fileName);
|
||||
onTypeRootFileChanged(project: ConfiguredProject, fileOrFolder: NormalizedPath) {
|
||||
project.getCachedServerHost().addOrDeleteFileOrFolder(fileOrFolder, this.toPath(fileOrFolder));
|
||||
project.updateTypes();
|
||||
this.delayUpdateProjectGraphAndInferredProjectsRefresh(project);
|
||||
}
|
||||
@@ -707,15 +707,15 @@ namespace ts.server {
|
||||
* @param fileName the absolute file name that changed in watched directory
|
||||
*/
|
||||
/* @internal */
|
||||
onFileAddOrRemoveInWatchedDirectoryOfProject(project: ConfiguredProject, fileName: NormalizedPath) {
|
||||
project.getCachedServerHost().addOrDeleteFileOrFolder(fileName);
|
||||
onFileAddOrRemoveInWatchedDirectoryOfProject(project: ConfiguredProject, fileOrFolder: NormalizedPath) {
|
||||
project.getCachedServerHost().addOrDeleteFileOrFolder(fileOrFolder, this.toPath(fileOrFolder));
|
||||
const configFilename = project.getConfigFilePath();
|
||||
|
||||
// If a change was made inside "folder/file", node will trigger the callback twice:
|
||||
// one with the fileName being "folder/file", and the other one with "folder".
|
||||
// We don't respond to the second one.
|
||||
if (fileName && !isSupportedSourceFileName(fileName, project.getCompilerOptions(), this.hostConfiguration.extraFileExtensions)) {
|
||||
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileName}`);
|
||||
if (fileOrFolder && !isSupportedSourceFileName(fileOrFolder, project.getCompilerOptions(), this.hostConfiguration.extraFileExtensions)) {
|
||||
this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileOrFolder}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
/// <reference path="..\compiler\resolutionCache.ts" />
|
||||
|
||||
namespace ts.server {
|
||||
/*@internal*/
|
||||
export class CachedServerHost implements ServerHost {
|
||||
args: string[];
|
||||
newLine: string;
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
|
||||
private readonly cachedHost: CachedHost;
|
||||
private readonly cachedPartialSystem: CachedPartialSystem;
|
||||
|
||||
readonly trace: (s: string) => void;
|
||||
readonly realpath?: (path: string) => string;
|
||||
@@ -24,7 +25,7 @@ namespace ts.server {
|
||||
if (this.host.realpath) {
|
||||
this.realpath = path => this.host.realpath(path);
|
||||
}
|
||||
this.cachedHost = createCachedHost(host);
|
||||
this.cachedPartialSystem = createCachedPartialSystem(host);
|
||||
}
|
||||
|
||||
write(s: string) {
|
||||
@@ -32,7 +33,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
writeFile(fileName: string, data: string, writeByteOrderMark?: boolean) {
|
||||
this.cachedHost.writeFile(fileName, data, writeByteOrderMark);
|
||||
this.cachedPartialSystem.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
resolvePath(path: string) {
|
||||
@@ -48,7 +49,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getCurrentDirectory() {
|
||||
return this.cachedHost.getCurrentDirectory();
|
||||
return this.cachedPartialSystem.getCurrentDirectory();
|
||||
}
|
||||
|
||||
exit(exitCode?: number) {
|
||||
@@ -61,32 +62,35 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getDirectories(rootDir: string) {
|
||||
return this.cachedHost.getDirectories(rootDir);
|
||||
return this.cachedPartialSystem.getDirectories(rootDir);
|
||||
}
|
||||
|
||||
readDirectory(rootDir: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[] {
|
||||
return this.cachedHost.readDirectory(rootDir, extensions, excludes, includes, depth);
|
||||
return this.cachedPartialSystem.readDirectory(rootDir, extensions, excludes, includes, depth);
|
||||
}
|
||||
|
||||
fileExists(fileName: string): boolean {
|
||||
return this.cachedHost.fileExists(fileName);
|
||||
return this.cachedPartialSystem.fileExists(fileName);
|
||||
}
|
||||
|
||||
directoryExists(dirPath: string) {
|
||||
return this.cachedHost.directoryExists(dirPath);
|
||||
return this.cachedPartialSystem.directoryExists(dirPath);
|
||||
}
|
||||
|
||||
readFile(path: string, encoding?: string): string {
|
||||
return this.host.readFile(path, encoding);
|
||||
}
|
||||
|
||||
addOrDeleteFileOrFolder(fileOrFolder: NormalizedPath, fileOrFolderPath: Path) {
|
||||
return this.cachedPartialSystem.addOrDeleteFileOrFolder(fileOrFolder, fileOrFolderPath);
|
||||
}
|
||||
|
||||
addOrDeleteFileOrFolder(fileOrFolder: NormalizedPath) {
|
||||
return this.cachedHost.addOrDeleteFileOrFolder(fileOrFolder);
|
||||
addOrDeleteFile(file: string, path: Path, eventKind: FileWatcherEventKind) {
|
||||
return this.cachedPartialSystem.addOrDeleteFile(file, path, eventKind);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
return this.cachedHost.clearCache();
|
||||
return this.cachedPartialSystem.clearCache();
|
||||
}
|
||||
|
||||
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]) {
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace ts.server {
|
||||
this.resolutionCache = createResolutionCache(
|
||||
fileName => this.projectService.toPath(fileName),
|
||||
() => this.compilerOptions,
|
||||
(failedLookupLocation, containingFile, name) => this.watchFailedLookupLocation(failedLookupLocation, containingFile, name),
|
||||
(failedLookupLocation, failedLookupLocationPath, containingFile, name) => this.watchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, containingFile, name),
|
||||
s => this.projectService.logger.info(s),
|
||||
(primaryResult, moduleName, compilerOptions, host) => resolveWithGlobalCache(primaryResult, moduleName, compilerOptions, host,
|
||||
this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined, this.getProjectName())
|
||||
@@ -235,12 +235,12 @@ namespace ts.server {
|
||||
this.markAsDirty();
|
||||
}
|
||||
|
||||
private watchFailedLookupLocation(failedLookupLocation: string, containingFile: string, name: string) {
|
||||
private watchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path, containingFile: string, name: string) {
|
||||
// There is some kind of change in the failed lookup location, update the program
|
||||
return this.projectService.addFileWatcher(WatchType.FailedLookupLocation, this, failedLookupLocation, (__fileName, eventKind) => {
|
||||
return this.projectService.addFileWatcher(WatchType.FailedLookupLocation, this, failedLookupLocation, (fileName, eventKind) => {
|
||||
this.projectService.logger.info(`Watcher: FailedLookupLocations: Status: ${FileWatcherEventKind[eventKind]}: Location: ${failedLookupLocation}, containingFile: ${containingFile}, name: ${name}`);
|
||||
if (this.projectKind === ProjectKind.Configured) {
|
||||
(this.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(toNormalizedPath(failedLookupLocation));
|
||||
(this.lsHost.host as CachedServerHost).addOrDeleteFile(fileName, failedLookupLocationPath, eventKind);
|
||||
}
|
||||
this.resolutionCache.invalidateResolutionOfChangedFailedLookupLocation(failedLookupLocation);
|
||||
this.markAsDirty();
|
||||
@@ -719,16 +719,15 @@ namespace ts.server {
|
||||
private addMissingFileWatcher(missingFilePath: Path) {
|
||||
const fileWatcher = this.projectService.addFileWatcher(
|
||||
WatchType.MissingFilePath, this, missingFilePath,
|
||||
(filename, eventKind) => {
|
||||
(fileName, eventKind) => {
|
||||
if (this.projectKind === ProjectKind.Configured) {
|
||||
(this.lsHost.host as CachedServerHost).addOrDeleteFile(fileName, missingFilePath, eventKind);
|
||||
}
|
||||
|
||||
if (eventKind === FileWatcherEventKind.Created && this.missingFilesMap.has(missingFilePath)) {
|
||||
this.missingFilesMap.delete(missingFilePath);
|
||||
this.closeMissingFileWatcher(missingFilePath, fileWatcher, WatcherCloseReason.FileCreated);
|
||||
|
||||
if (this.projectKind === ProjectKind.Configured) {
|
||||
const absoluteNormalizedPath = getNormalizedAbsolutePath(filename, getDirectoryPath(missingFilePath));
|
||||
(this.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(toNormalizedPath(absoluteNormalizedPath));
|
||||
}
|
||||
|
||||
// When a missing file is created, we should update the graph.
|
||||
this.markAsDirty();
|
||||
this.projectService.delayUpdateProjectGraphAndInferredProjectsRefresh(this);
|
||||
@@ -1076,6 +1075,7 @@ namespace ts.server {
|
||||
return super.updateGraph();
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getCachedServerHost() {
|
||||
return this.lsHost.host as CachedServerHost;
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace ts.server {
|
||||
detachAllProjects() {
|
||||
for (const p of this.containingProjects) {
|
||||
if (p.projectKind === ProjectKind.Configured) {
|
||||
(p.lsHost.host as CachedServerHost).addOrDeleteFileOrFolder(this.fileName);
|
||||
(p.lsHost.host as CachedServerHost).addOrDeleteFile(this.fileName, this.path, FileWatcherEventKind.Deleted);
|
||||
}
|
||||
const isInfoRoot = p.isRoot(this);
|
||||
// detach is unnecessary since we'll clean the list of containing projects anyways
|
||||
|
||||
Reference in New Issue
Block a user