Skip to content

Commit 43c2610

Browse files
committed
More functions moved from system to WatchCompilerHost
1 parent 944f8b8 commit 43c2610

14 files changed

Lines changed: 479 additions & 334 deletions

File tree

src/compiler/core.ts

Lines changed: 6 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,9 @@ namespace ts {
13981398
/** Returns its argument. */
13991399
export function identity<T>(x: T) { return x; }
14001400

1401+
/** Returns lower case string */
1402+
export function toLowerCase(x: string) { return x.toLowerCase(); }
1403+
14011404
/** Throws an error because a function is not implemented. */
14021405
export function notImplemented(): never {
14031406
throw new Error("Not implemented");
@@ -2877,9 +2880,7 @@ namespace ts {
28772880

28782881
export type GetCanonicalFileName = (fileName: string) => string;
28792882
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): GetCanonicalFileName {
2880-
return useCaseSensitiveFileNames
2881-
? ((fileName) => fileName)
2882-
: ((fileName) => fileName.toLowerCase());
2883+
return useCaseSensitiveFileNames ? identity : toLowerCase;
28832884
}
28842885

28852886
/**
@@ -3000,215 +3001,7 @@ namespace ts {
30003001

30013002
export function assertTypeIsNever(_: never): void { } // tslint:disable-line no-empty
30023003

3003-
export interface FileAndDirectoryExistence {
3004-
fileExists: boolean;
3005-
directoryExists: boolean;
3006-
}
3007-
3008-
export interface CachedDirectoryStructureHost extends DirectoryStructureHost {
3009-
/** Returns the queried result for the file exists and directory exists if at all it was done */
3010-
addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path): FileAndDirectoryExistence | undefined;
3011-
addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind): void;
3012-
clearCache(): void;
3013-
}
3014-
3015-
interface MutableFileSystemEntries {
3016-
readonly files: string[];
3017-
readonly directories: string[];
3018-
}
3019-
3020-
export function createCachedDirectoryStructureHost(host: DirectoryStructureHost): CachedDirectoryStructureHost {
3021-
const cachedReadDirectoryResult = createMap<MutableFileSystemEntries>();
3022-
const getCurrentDirectory = memoize(() => host.getCurrentDirectory());
3023-
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
3024-
return {
3025-
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames,
3026-
readFile: (path, encoding) => host.readFile(path, encoding),
3027-
writeFile,
3028-
fileExists,
3029-
directoryExists,
3030-
createDirectory,
3031-
getCurrentDirectory,
3032-
getDirectories,
3033-
readDirectory,
3034-
addOrDeleteFileOrDirectory,
3035-
addOrDeleteFile,
3036-
clearCache,
3037-
exit: code => host.exit(code)
3038-
};
3039-
3040-
function toPath(fileName: string) {
3041-
return ts.toPath(fileName, getCurrentDirectory(), getCanonicalFileName);
3042-
}
3043-
3044-
function getCachedFileSystemEntries(rootDirPath: Path): MutableFileSystemEntries | undefined {
3045-
return cachedReadDirectoryResult.get(rootDirPath);
3046-
}
3047-
3048-
function getCachedFileSystemEntriesForBaseDir(path: Path): MutableFileSystemEntries | undefined {
3049-
return getCachedFileSystemEntries(getDirectoryPath(path));
3050-
}
3051-
3052-
function getBaseNameOfFileName(fileName: string) {
3053-
return getBaseFileName(normalizePath(fileName));
3054-
}
3055-
3056-
function createCachedFileSystemEntries(rootDir: string, rootDirPath: Path) {
3057-
const resultFromHost: MutableFileSystemEntries = {
3058-
files: map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/["*.*"]), getBaseNameOfFileName) || [],
3059-
directories: host.getDirectories(rootDir) || []
3060-
};
3061-
3062-
cachedReadDirectoryResult.set(rootDirPath, resultFromHost);
3063-
return resultFromHost;
3064-
}
3065-
3066-
/**
3067-
* If the readDirectory result was already cached, it returns that
3068-
* Otherwise gets result from host and caches it.
3069-
* The host request is done under try catch block to avoid caching incorrect result
3070-
*/
3071-
function tryReadDirectory(rootDir: string, rootDirPath: Path): MutableFileSystemEntries | undefined {
3072-
const cachedResult = getCachedFileSystemEntries(rootDirPath);
3073-
if (cachedResult) {
3074-
return cachedResult;
3075-
}
3076-
3077-
try {
3078-
return createCachedFileSystemEntries(rootDir, rootDirPath);
3079-
}
3080-
catch (_e) {
3081-
// If there is exception to read directories, dont cache the result and direct the calls to host
3082-
Debug.assert(!cachedReadDirectoryResult.has(rootDirPath));
3083-
return undefined;
3084-
}
3085-
}
3086-
3087-
function fileNameEqual(name1: string, name2: string) {
3088-
return getCanonicalFileName(name1) === getCanonicalFileName(name2);
3089-
}
3090-
3091-
function hasEntry(entries: ReadonlyArray<string>, name: string) {
3092-
return some(entries, file => fileNameEqual(file, name));
3093-
}
3094-
3095-
function updateFileSystemEntry(entries: string[], baseName: string, isValid: boolean) {
3096-
if (hasEntry(entries, baseName)) {
3097-
if (!isValid) {
3098-
return filterMutate(entries, entry => !fileNameEqual(entry, baseName));
3099-
}
3100-
}
3101-
else if (isValid) {
3102-
return entries.push(baseName);
3103-
}
3104-
}
3105-
3106-
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
3107-
const path = toPath(fileName);
3108-
const result = getCachedFileSystemEntriesForBaseDir(path);
3109-
if (result) {
3110-
updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true);
3111-
}
3112-
return host.writeFile(fileName, data, writeByteOrderMark);
3113-
}
3114-
3115-
function fileExists(fileName: string): boolean {
3116-
const path = toPath(fileName);
3117-
const result = getCachedFileSystemEntriesForBaseDir(path);
3118-
return result && hasEntry(result.files, getBaseNameOfFileName(fileName)) ||
3119-
host.fileExists(fileName);
3120-
}
3121-
3122-
function directoryExists(dirPath: string): boolean {
3123-
const path = toPath(dirPath);
3124-
return cachedReadDirectoryResult.has(path) || host.directoryExists(dirPath);
3125-
}
3126-
3127-
function createDirectory(dirPath: string) {
3128-
const path = toPath(dirPath);
3129-
const result = getCachedFileSystemEntriesForBaseDir(path);
3130-
const baseFileName = getBaseNameOfFileName(dirPath);
3131-
if (result) {
3132-
updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true);
3133-
}
3134-
host.createDirectory(dirPath);
3135-
}
3136-
3137-
function getDirectories(rootDir: string): string[] {
3138-
const rootDirPath = toPath(rootDir);
3139-
const result = tryReadDirectory(rootDir, rootDirPath);
3140-
if (result) {
3141-
return result.directories.slice();
3142-
}
3143-
return host.getDirectories(rootDir);
3144-
}
3145-
3146-
function readDirectory(rootDir: string, extensions?: ReadonlyArray<string>, excludes?: ReadonlyArray<string>, includes?: ReadonlyArray<string>, depth?: number): string[] {
3147-
const rootDirPath = toPath(rootDir);
3148-
const result = tryReadDirectory(rootDir, rootDirPath);
3149-
if (result) {
3150-
return matchFiles(rootDir, extensions, excludes, includes, host.useCaseSensitiveFileNames, getCurrentDirectory(), depth, getFileSystemEntries);
3151-
}
3152-
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
3153-
3154-
function getFileSystemEntries(dir: string) {
3155-
const path = toPath(dir);
3156-
if (path === rootDirPath) {
3157-
return result;
3158-
}
3159-
return getCachedFileSystemEntries(path) || createCachedFileSystemEntries(dir, path);
3160-
}
3161-
}
3162-
3163-
function addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path) {
3164-
const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath);
3165-
if (existingResult) {
3166-
// Just clear the cache for now
3167-
// For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated
3168-
clearCache();
3169-
}
3170-
else {
3171-
// This was earlier a file (hence not in cached directory contents)
3172-
// or we never cached the directory containing it
3173-
const parentResult = getCachedFileSystemEntriesForBaseDir(fileOrDirectoryPath);
3174-
if (parentResult) {
3175-
const baseName = getBaseNameOfFileName(fileOrDirectory);
3176-
if (parentResult) {
3177-
const fsQueryResult: FileAndDirectoryExistence = {
3178-
fileExists: host.fileExists(fileOrDirectoryPath),
3179-
directoryExists: host.directoryExists(fileOrDirectoryPath)
3180-
};
3181-
if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) {
3182-
// Folder added or removed, clear the cache instead of updating the folder and its structure
3183-
clearCache();
3184-
}
3185-
else {
3186-
// No need to update the directory structure, just files
3187-
updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists);
3188-
}
3189-
return fsQueryResult;
3190-
}
3191-
}
3192-
}
3193-
}
3194-
3195-
function addOrDeleteFile(fileName: string, filePath: Path, eventKind: FileWatcherEventKind) {
3196-
if (eventKind === FileWatcherEventKind.Changed) {
3197-
return;
3198-
}
3199-
3200-
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath);
3201-
if (parentResult) {
3202-
updateFilesOfFileSystemEntry(parentResult, getBaseNameOfFileName(fileName), eventKind === FileWatcherEventKind.Created);
3203-
}
3204-
}
3205-
3206-
function updateFilesOfFileSystemEntry(parentResult: MutableFileSystemEntries, baseName: string, fileExists: boolean) {
3207-
updateFileSystemEntry(parentResult.files, baseName, fileExists);
3208-
}
3209-
3210-
function clearCache() {
3211-
cachedReadDirectoryResult.clear();
3212-
}
3004+
export function getBoundFunction<T extends Function>(method: T | undefined, methodOf: {}): T | undefined {
3005+
return method && method.bind(methodOf);
32133006
}
32143007
}

src/compiler/program.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ namespace ts {
191191
readFile: fileName => sys.readFile(fileName),
192192
trace: (s: string) => sys.write(s + newLine),
193193
directoryExists: directoryName => sys.directoryExists(directoryName),
194-
getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "",
195194
getDirectories: (path: string) => sys.getDirectories(path),
196195
realpath
197196
};

src/compiler/resolutionCache.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace ts {
4747
onInvalidatedResolution(): void;
4848
watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher;
4949
onChangedAutomaticTypeDirectiveNames(): void;
50-
getCachedDirectoryStructureHost?(): CachedDirectoryStructureHost;
50+
getCachedDirectoryStructureHost(): CachedDirectoryStructureHost | undefined;
5151
projectName?: string;
5252
getGlobalCache?(): string | undefined;
5353
writeLog(s: string): void;
@@ -87,6 +87,7 @@ namespace ts {
8787
const perDirectoryResolvedTypeReferenceDirectives = createMap<Map<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>>();
8888

8989
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory());
90+
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
9091

9192
/**
9293
* These are the extensions that failed lookup files will have by default,
@@ -467,9 +468,9 @@ namespace ts {
467468
function createDirectoryWatcher(directory: string, dirPath: Path) {
468469
return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => {
469470
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
470-
if (resolutionHost.getCachedDirectoryStructureHost) {
471+
if (cachedDirectoryStructureHost) {
471472
// Since the file existance changed, update the sourceFiles cache
472-
resolutionHost.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
473+
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
473474
}
474475

475476
// If the files are added to project root or node_modules directory, always run through the invalidation process
@@ -596,9 +597,9 @@ namespace ts {
596597
// Create new watch and recursive info
597598
return resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => {
598599
const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory);
599-
if (resolutionHost.getCachedDirectoryStructureHost) {
600+
if (cachedDirectoryStructureHost) {
600601
// Since the file existance changed, update the sourceFiles cache
601-
resolutionHost.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
602+
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
602603
}
603604

604605
// For now just recompile

src/compiler/sys.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,36 @@ namespace ts {
3030
mtime?: Date;
3131
}
3232

33-
/**
34-
* Partial interface of the System thats needed to support the caching of directory structure
35-
*/
36-
export interface DirectoryStructureHost {
37-
useCaseSensitiveFileNames: boolean;
38-
readFile(path: string, encoding?: string): string | undefined;
39-
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
40-
fileExists(path: string): boolean;
41-
directoryExists(path: string): boolean;
42-
createDirectory(path: string): void;
43-
getCurrentDirectory(): string;
44-
getDirectories(path: string): string[];
45-
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
46-
exit(exitCode?: number): void;
47-
}
48-
49-
export interface System extends DirectoryStructureHost {
50-
newLine: string;
33+
export interface System {
5134
args: string[];
35+
newLine: string;
36+
useCaseSensitiveFileNames: boolean;
5237
write(s: string): void;
38+
readFile(path: string, encoding?: string): string | undefined;
5339
getFileSize?(path: string): number;
40+
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
5441
/**
5542
* @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that
5643
* use native OS file watching
5744
*/
5845
watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
5946
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
6047
resolvePath(path: string): string;
48+
fileExists(path: string): boolean;
49+
directoryExists(path: string): boolean;
50+
createDirectory(path: string): void;
6151
getExecutingFilePath(): string;
52+
getCurrentDirectory(): string;
53+
getDirectories(path: string): string[];
54+
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
6255
getModifiedTime?(path: string): Date;
6356
/**
6457
* This should be cryptographically secure.
6558
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
6659
*/
6760
createHash?(data: string): string;
6861
getMemoryUsage?(): number;
62+
exit(exitCode?: number): void;
6963
realpath?(path: string): string;
7064
/*@internal*/ getEnvironmentVariable(name: string): string;
7165
/*@internal*/ tryEnableSourceMapsForHost?(): void;

src/compiler/tsc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ namespace ts {
110110

111111
const commandLineOptions = commandLine.options;
112112
if (configFileName) {
113-
const configParseResult = parseConfigFile(configFileName, commandLineOptions, sys, reportDiagnostic);
113+
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic);
114114
udpateReportDiagnostic(configParseResult.options);
115115
if (isWatchSet(configParseResult.options)) {
116116
reportWatchModeWithoutSysSupport();

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4327,7 +4327,6 @@ namespace ts {
43274327
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
43284328
*/
43294329
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
4330-
getEnvironmentVariable?(name: string): string;
43314330
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions): void;
43324331
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
43334332
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;

0 commit comments

Comments
 (0)