Use fileName instead of Path when dealing with file systems directly

This commit is contained in:
zhengbli 2016-03-23 12:49:34 -07:00
parent 9094e01e75
commit e9b514cf8a
2 changed files with 51 additions and 55 deletions

View file

@ -1,8 +1,8 @@
/// <reference path="core.ts"/>
namespace ts {
export type FileWatcherCallback = (path: string, removed?: boolean) => void;
export type DirectoryWatcherCallback = (path: string) => void;
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
export type DirectoryWatcherCallback = (directoryName: string) => void;
export interface System {
args: string[];
@ -11,7 +11,7 @@ namespace ts {
write(s: string): void;
readFile(path: string, encoding?: string): string;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher;
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
resolvePath(path: string): string;
fileExists(path: string): boolean;
@ -25,7 +25,7 @@ namespace ts {
}
interface WatchedFile {
filePath: Path;
fileName: string;
callback: FileWatcherCallback;
mtime?: Date;
}
@ -35,7 +35,7 @@ namespace ts {
}
export interface DirectoryWatcher extends FileWatcher {
directoryPath: Path;
directoryName: string;
referenceCount: number;
}
@ -244,13 +244,13 @@ namespace ts {
return;
}
_fs.stat(watchedFile.filePath, (err: any, stats: any) => {
_fs.stat(watchedFile.fileName, (err: any, stats: any) => {
if (err) {
watchedFile.callback(watchedFile.filePath);
watchedFile.callback(watchedFile.fileName);
}
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
watchedFile.mtime = getModifiedTime(watchedFile.filePath);
watchedFile.callback(watchedFile.filePath, watchedFile.mtime.getTime() === 0);
watchedFile.mtime = getModifiedTime(watchedFile.fileName);
watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0);
}
});
}
@ -278,11 +278,11 @@ namespace ts {
}, interval);
}
function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile {
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
const file: WatchedFile = {
filePath,
fileName,
callback,
mtime: getModifiedTime(filePath)
mtime: getModifiedTime(fileName)
};
watchedFiles.push(file);
@ -306,26 +306,26 @@ namespace ts {
}
function createWatchedFileSet() {
const dirWatchers = createFileMap<DirectoryWatcher>();
const dirWatchers: Map<DirectoryWatcher> = {};
// One file can have multiple watchers
const fileWatcherCallbacks = createFileMap<FileWatcherCallback[]>();
const fileWatcherCallbacks: Map<FileWatcherCallback[]> = {};
return { addFile, removeFile };
function reduceDirWatcherRefCountForFile(filePath: Path) {
const dirPath = getDirectoryPath(filePath);
if (dirWatchers.contains(dirPath)) {
const watcher = dirWatchers.get(dirPath);
function reduceDirWatcherRefCountForFile(fileName: string) {
const dirName = getDirectoryPath(fileName);
if (hasProperty(dirWatchers, dirName)) {
const watcher = dirWatchers[dirName];
watcher.referenceCount -= 1;
if (watcher.referenceCount <= 0) {
watcher.close();
dirWatchers.remove(dirPath);
delete dirWatchers[dirName];
}
}
}
function addDirWatcher(dirPath: Path): void {
if (dirWatchers.contains(dirPath)) {
const watcher = dirWatchers.get(dirPath);
function addDirWatcher(dirPath: string): void {
if (hasProperty(dirWatchers, dirPath)) {
const watcher = dirWatchers[dirPath];
watcher.referenceCount += 1;
return;
}
@ -336,52 +336,52 @@ namespace ts {
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
);
watcher.referenceCount = 1;
dirWatchers.set(dirPath, watcher);
dirWatchers[dirPath] = watcher;
return;
}
function addFileWatcherCallback(filePath: Path, callback: FileWatcherCallback): void {
if (fileWatcherCallbacks.contains(filePath)) {
fileWatcherCallbacks.get(filePath).push(callback);
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
if (hasProperty(fileWatcherCallbacks, filePath)) {
fileWatcherCallbacks[filePath].push(callback);
}
else {
fileWatcherCallbacks.set(filePath, [callback]);
fileWatcherCallbacks[filePath] = [callback];
}
}
function addFile(filePath: Path, callback: FileWatcherCallback): WatchedFile {
addFileWatcherCallback(filePath, callback);
addDirWatcher(getDirectoryPath(filePath));
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
addFileWatcherCallback(fileName, callback);
addDirWatcher(getDirectoryPath(fileName));
return { filePath, callback };
return { fileName, callback };
}
function removeFile(watchedFile: WatchedFile) {
removeFileWatcherCallback(watchedFile.filePath, watchedFile.callback);
reduceDirWatcherRefCountForFile(watchedFile.filePath);
removeFileWatcherCallback(watchedFile.fileName, watchedFile.callback);
reduceDirWatcherRefCountForFile(watchedFile.fileName);
}
function removeFileWatcherCallback(filePath: Path, callback: FileWatcherCallback) {
if (fileWatcherCallbacks.contains(filePath)) {
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks.get(filePath));
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
if (hasProperty(fileWatcherCallbacks, filePath)) {
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks[filePath]);
if (newCallbacks.length === 0) {
fileWatcherCallbacks.remove(filePath);
delete fileWatcherCallbacks[filePath];
}
else {
fileWatcherCallbacks.set(filePath, newCallbacks);
fileWatcherCallbacks[filePath] = newCallbacks;
}
}
}
function fileEventHandler(eventName: string, relativeFileName: string, baseDirPath: Path) {
function fileEventHandler(eventName: string, relativeFileName: string, baseDirPath: string) {
// When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined"
const filePath = typeof relativeFileName !== "string"
const fileName = typeof relativeFileName !== "string"
? undefined
: toPath(relativeFileName, baseDirPath, createGetCanonicalFileName(sys.useCaseSensitiveFileNames));
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
// Some applications save a working file via rename operations
if ((eventName === "change" || eventName === "rename") && fileWatcherCallbacks.contains(filePath)) {
for (const fileCallback of fileWatcherCallbacks.get(filePath)) {
fileCallback(filePath);
if ((eventName === "change" || eventName === "rename") && hasProperty(fileWatcherCallbacks, fileName)) {
for (const fileCallback of fileWatcherCallbacks[fileName]) {
fileCallback(fileName);
}
}
}
@ -526,18 +526,18 @@ namespace ts {
},
readFile,
writeFile,
watchFile: (filePath, callback) => {
watchFile: (fileName, callback) => {
// Node 4.0 stabilized the `fs.watch` function on Windows which avoids polling
// and is more efficient than `fs.watchFile` (ref: https://github.com/nodejs/node/pull/2649
// and https://github.com/Microsoft/TypeScript/issues/4643), therefore
// if the current node.js version is newer than 4, use `fs.watch` instead.
const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet;
const watchedFile = watchSet.addFile(filePath, callback);
const watchedFile = watchSet.addFile(fileName, callback);
return {
close: () => watchSet.removeFile(watchedFile)
};
},
watchDirectory: (path, callback, recursive) => {
watchDirectory: (directoryName, callback, recursive) => {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
let options: any;
@ -549,7 +549,7 @@ namespace ts {
}
return _fs.watch(
path,
directoryName,
options,
(eventName: string, relativeFileName: string) => {
// In watchDirectory we only care about adding and removing files (when event name is
@ -557,7 +557,7 @@ namespace ts {
// event name is "change")
if (eventName === "rename") {
// When deleting a file, the passed baseFileName is null
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(path, relativeFileName)));
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(directoryName, relativeFileName)));
};
}
);

View file

@ -1006,9 +1006,7 @@ namespace ts.server {
info.setFormatOptions(this.getFormatCodeOptions());
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
info.fileWatcher = this.host.watchFile(
toPath(fileName, fileName, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
_ => { this.watchedFileChanged(fileName); });
info.fileWatcher = this.host.watchFile(fileName, _ => { this.watchedFileChanged(fileName); });
}
}
}
@ -1227,9 +1225,7 @@ namespace ts.server {
}
}
project.finishGraph();
project.projectFileWatcher = this.host.watchFile(
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
_ => this.watchedProjectConfigFileChanged(project));
project.projectFileWatcher = this.host.watchFile(configFilename, _ => this.watchedProjectConfigFileChanged(project));
this.log("Add recursive watcher for: " + ts.getDirectoryPath(configFilename));
project.directoryWatcher = this.host.watchDirectory(
ts.getDirectoryPath(configFilename),