diff --git a/src/fileSystemRouter.ts b/src/fileSystemRouter.ts index ac15ed2..4982433 100644 --- a/src/fileSystemRouter.ts +++ b/src/fileSystemRouter.ts @@ -1,30 +1,75 @@ +// 导入 VSCode 模块,用于访问 VSCode 的 API import * as vscode from 'vscode'; +// 从 './flags' 模块中导入 getFlag 和 subscribeToGlobalFlags 函数 import { getFlag, subscribeToGlobalFlags } from './flags'; +// 从 './logging' 模块中导入 Logging 类 import { Logging } from './logging'; +// 从 './manager' 模块中导入 Manager 类型 import type { Manager } from './manager'; +// 定义一个包含所有可能的调试标志的数组 const ALL_DEBUG_FLAGS = [ - 'stat', 'readDirectory', 'createDirectory', - 'readFile', 'writeFile', 'delete', 'rename', -].map(v => v.toLowerCase()); + // 文件状态检查操作的调试标志 + 'stat', + // 读取目录操作的调试标志 + 'readDirectory', + // 创建目录操作的调试标志 + 'createDirectory', + // 读取文件操作的调试标志 + 'readFile', + // 写入文件操作的调试标志 + 'writeFile', + // 删除文件或目录操作的调试标志 + 'delete', + // 重命名文件或目录操作的调试标志 + 'rename', +].map(v => v.toLowerCase()); // 将所有标志转换为小写形式,以便于比较和匹配 +/** + * FileSystemRouter 类实现了 vscode.FileSystemProvider 接口,用于处理文件系统的各种操作 + */ export class FileSystemRouter implements vscode.FileSystemProvider { + // 定义一个事件,用于通知文件系统的变化 public onDidChangeFile: vscode.Event; + // 定义一个事件发射器,用于发射文件系统变化的事件 protected onDidChangeFileEmitter = new vscode.EventEmitter(); + // 定义一个数组,用于存储调试标志 protected debugFlags: string[]; + /** + * 构造函数,初始化 FileSystemRouter 类的实例 + * @param manager - Manager 类的实例,用于管理文件系统 + */ constructor(protected readonly manager: Manager) { + // 将 onDidChangeFileEmitter 的事件绑定到 onDidChangeFile this.onDidChangeFile = this.onDidChangeFileEmitter.event; + // 订阅全局标志,当全局标志发生变化时,更新 debugFlags subscribeToGlobalFlags(() => { + // 获取 DEBUG_FSR 标志的值,并将其转换为小写,然后分割成数组 this.debugFlags = `${getFlag('DEBUG_FSR')?.[0] || ''}`.toLowerCase().split(/,\s*|\s+/g); + // 如果 debugFlags 中包含 'all',则将 ALL_DEBUG_FLAGS 中的所有标志添加到 debugFlags 中 if (this.debugFlags.includes('all')) this.debugFlags.push(...ALL_DEBUG_FLAGS); }); } + /** + * 断言文件系统是否存在,如果不存在则创建一个新的文件系统 + * @param uri - 文件系统的 URI + * @returns 文件系统的实例 + */ public async assertFs(uri: vscode.Uri): Promise { + // 从 manager 中获取文件系统实例 const fs = this.manager.getFs(uri); + // 如果文件系统实例存在,则返回该实例 if (fs) return fs; + // 如果文件系统实例不存在,则创建一个新的文件系统实例并返回 return this.manager.createFileSystem(uri.authority); } /* FileSystemProvider */ + /** + * 监视文件系统的变化 + * @param uri - 文件系统的 URI + * @param options - 监视选项 + * @returns 一个可取消的订阅,用于停止监视 + */ public watch(uri: vscode.Uri, options: { recursive: boolean; excludes: string[]; }): vscode.Disposable { // TODO: Store watched files/directories in an array and periodically check if they're modified /*let disp = () => {}; @@ -34,42 +79,98 @@ export class FileSystemRouter implements vscode.FileSystemProvider { return new vscode.Disposable(() => disp());*/ return new vscode.Disposable(() => { }); } + /** + * 获取文件或目录的状态 + * @param uri - 文件或目录的 URI + * @returns 文件或目录的状态 + */ public async stat(uri: vscode.Uri): Promise { + // 如果 debugFlags 中包含 'stat',则输出调试信息 if (this.debugFlags.includes('stat')) Logging.debug`Performing stat for ${uri}`; + // 获取文件系统实例,并调用其 stat 方法 return (await this.assertFs(uri)).stat(uri); } + /** + * 读取目录的内容 + * @param uri - 目录的 URI + * @returns 目录内容的数组,每个元素包含文件名和文件类型 + */ public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> { + // 如果 debugFlags 中包含 'readdirectory',则输出调试信息 if (this.debugFlags.includes('readdirectory')) Logging.debug`Reading directory ${uri}`; + // 获取文件系统实例,并调用其 readDirectory 方法 return (await this.assertFs(uri)).readDirectory(uri); } + /** + * 创建目录 + * @param uri - 目录的 URI + * @returns 一个 Promise,当目录创建成功时解析 + */ public async createDirectory(uri: vscode.Uri): Promise { + // 如果 debugFlags 中包含 'createdirectory',则输出调试信息 if (this.debugFlags.includes('createdirectory')) Logging.debug`Creating directory ${uri}`; + // 获取文件系统实例,并调用其 createDirectory 方法 return (await this.assertFs(uri)).createDirectory(uri); } + /** + * 读取文件的内容 + * @param uri - 文件的 URI + * @returns 文件内容的 Uint8Array + */ public async readFile(uri: vscode.Uri): Promise { + // 如果 debugFlags 中包含 'readfile',则输出调试信息 if (this.debugFlags.includes('readfile')) Logging.debug`Reading ${uri}`; + // 获取文件系统实例,并调用其 readFile 方法 return (await this.assertFs(uri)).readFile(uri); } + /** + * 写入文件的内容 + * @param uri - 文件的 URI + * @param content - 要写入的内容 + * @param options - 写入选项 + * @returns 一个 Promise,当文件写入成功时解析 + */ public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean; }): Promise { + // 如果 debugFlags 中包含 'writefile',则输出调试信息 if (this.debugFlags.includes('writefile')) Logging.debug`Writing ${content.length} bytes to ${uri} (options: ${options})`; + // 获取文件系统实例,并调用其 writeFile 方法 return (await this.assertFs(uri)).writeFile(uri, content, options); } + /** + * 删除文件或目录 + * @param uri - 文件或目录的 URI + * @param options - 删除选项 + * @returns 一个 Promise,当文件或目录删除成功时解析 + */ public async delete(uri: vscode.Uri, options: { recursive: boolean; }): Promise { + // 如果 debugFlags 中包含 'delete',则输出调试信息 if (this.debugFlags.includes('delete')) Logging.debug`Deleting ${uri} (options: ${options})`; + // 获取文件系统实例,并调用其 delete 方法 return (await this.assertFs(uri)).delete(uri, options); } + /** + * 重命名文件或目录 + * @param oldUri - 旧的 URI + * @param newUri - 新的 URI + * @param options - 重命名选项 + * @returns 一个 Promise,当文件或目录重命名成功时解析 + */ public async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean; }): Promise { + // 如果 debugFlags 中包含 'rename',则输出调试信息 if (this.debugFlags.includes('rename')) Logging.debug`Renaming ${oldUri} to ${newUri}`; + // 获取旧的文件系统实例 const fs = await this.assertFs(oldUri); + // 如果新的文件系统实例与旧的不同,则抛出错误 if (fs !== (await this.assertFs(newUri))) throw new Error(`Can't rename between different SSH filesystems`); + // 调用文件系统实例的 rename 方法 return fs.rename(oldUri, newUri, options); } -} +} \ No newline at end of file