🦄 refactor(阅读代码): 补充extension.ts的说明

master
yetao 4 weeks ago
parent 2e36423f13
commit b1f50318a8

@ -1,161 +1,416 @@
// 导入 FileSystemConfig 类型,该类型定义了文件系统的配置
import type { FileSystemConfig } from 'common/fileSystemConfig';
// 导入 vscode 模块,该模块提供了 VS Code 扩展 API
import * as vscode from 'vscode';
// 导入 loadConfigs 和 reloadWorkspaceFolderConfigs 函数,这些函数用于加载和重新加载配置
import { loadConfigs, reloadWorkspaceFolderConfigs } from './config';
// 导入 Connection 类型,该类型定义了连接的配置
import type { Connection } from './connection';
// 导入 FileSystemRouter 类,该类用于处理文件系统的路由
import { FileSystemRouter } from './fileSystemRouter';
// 导入 Logging 类和 setDebug 函数,这些用于设置日志记录和调试模式
import { Logging, setDebug } from './logging';
// 导入 Manager 类,该类用于管理文件系统的连接和配置
import { Manager } from './manager';
// 导入 SSHPseudoTerminal 类型,该类型定义了 SSH 伪终端的配置
import type { SSHPseudoTerminal } from './pseudoTerminal';
// 导入 ConfigTreeProvider 和 ConnectionTreeProvider 类,这些类用于提供树形视图的数据
import { ConfigTreeProvider, ConnectionTreeProvider } from './treeViewManager';
// 导入 PickComplexOptions 类型、pickComplex 函数、pickConnection 函数、setAsAbsolutePath 函数和 setupWhenClauseContexts 函数,这些函数和类型用于处理复杂的选择和设置绝对路径等操作
import { PickComplexOptions, pickComplex, pickConnection, setAsAbsolutePath, setupWhenClauseContexts } from './ui-utils';
/**
*
* URI
*/
interface CommandHandler {
/** If set, a string/undefined prompts using the given options.
* If the input was a string, promptOptions.nameFilter is set to it */
/**
* 使/
* promptOptions.nameFilter
*/
promptOptions: PickComplexOptions;
/**
*
* @param string -
*/
handleString?(string: string): void;
/**
* URI
* @param uri - URI
*/
handleUri?(uri: vscode.Uri): void;
/**
*
* @param config -
*/
handleConfig?(config: FileSystemConfig): void;
/**
*
* @param connection -
*/
handleConnection?(connection: Connection): void;
/**
* SSH
* @param terminal - SSH
*/
handleTerminal?(terminal: SSHPseudoTerminal): void;
}
/** `findConfigs` in config.ts ignores URIs for still-connecting connections */
/**
* MANAGER Manager
* SSH
*/
export let MANAGER: Manager | undefined;
/**
* VS Code
*
*
*
* @param context -
*/
export function activate(context: vscode.ExtensionContext) {
// 通过 VS Code API 获取名为 'Kelvin.vscode-sshfs' 的扩展实例
const extension = vscode.extensions.getExtension('Kelvin.vscode-sshfs');
// 尝试获取扩展的版本号,如果扩展不存在,则版本号为 undefined
const version = extension?.packageJSON?.version;
// 使用 Logging 模块记录扩展激活的信息,包括版本和模式
Logging.info`Extension activated, version ${version}, mode ${context.extensionMode}`;
// 使用 Logging 模块记录当前运行的 VS Code 版本和进程版本信息
Logging.debug`Running VS Code version ${vscode.version} ${process.versions}`;
// 检查环境变量 VSCODE_SSHFS_DEBUG 是否设置为 true以启用调试模式
setDebug(process.env.VSCODE_SSHFS_DEBUG?.toLowerCase() === 'true');
// 从全局状态中获取版本历史记录,如果没有则初始化为空数组
const versionHistory = context.globalState.get<[string, number, number][]>('versionHistory', []);
// 获取版本历史记录中的最后一个版本
const lastVersion = versionHistory[versionHistory.length - 1];
// 检查是否存在上一个版本记录
if (!lastVersion) {
// 尝试从全局状态中获取旧版本记录(在 v1.21.0 之前的版本中使用)
const classicLastVersion = context.globalState.get<string>('lastVersion');
// 如果存在旧版本记录
if (classicLastVersion) {
// 记录日志,表明正在从旧版本记录切换到新版本历史记录
Logging.debug`Previously used ${classicLastVersion}, switching over to new version history`;
// 将旧版本记录添加到新版本历史记录中
versionHistory.push([classicLastVersion, Date.now(), Date.now()]);
} else {
// 记录日志,表明没有检测到之前的版本,可能是全新安装或安装了 v1.21.0 之前的版本
Logging.debug`No previous version detected. Fresh or pre-v1.21.0 installation?`;
}
// 将当前版本添加到版本历史记录中
versionHistory.push([version, Date.now(), Date.now()]);
// 如果存在上一个版本记录,但是版本号与当前版本不同
} else if (lastVersion[0]!== version) {
// 记录日志,表明之前使用的是不同的版本,现在是切换到当前版本后的首次启动
Logging.debug`Previously used ${lastVersion[0]}, currently first launch since switching to ${version}`;
// 将当前版本添加到版本历史记录中
versionHistory.push([version, Date.now(), Date.now()]);
// 如果存在上一个版本记录,且版本号与当前版本相同
} else {
// 更新上一个版本记录的最后更新时间为当前时间
lastVersion[2] = Date.now();
}
// 使用 Logging 模块记录版本历史记录,将版本历史记录中的每个版本号、创建时间和最后更新时间用冒号连接起来,并用大于号分隔
Logging.info`Version history: ${versionHistory.map(v => v.join(':')).join(' > ')}`;
// 将更新后的版本历史记录保存到全局状态中,以便下次扩展激活时可以读取
context.globalState.update('versionHistory', versionHistory);
// Really too bad we *need* the ExtensionContext for relative resources
// I really don't like having to pass context to *everything*, so let's do it this way
// 真的很糟糕我们确实需要扩展上下文ExtensionContext来获取相对资源。
// 我真的不喜欢必须将上下文传递给所有东西,所以让我们这样做吧。
// 将 context.asAbsolutePath 方法绑定到当前上下文中,并赋值给 setAsAbsolutePath 变量
setAsAbsolutePath(context.asAbsolutePath.bind(context));
// 创建一个 Manager 实例,并将其赋值给全局变量 MANAGER
const manager = MANAGER = new Manager(context);
// 定义一个函数,用于将订阅添加到 context.subscriptions 数组中
const subscribe = context.subscriptions.push.bind(context.subscriptions) as typeof context.subscriptions.push;
// 定义一个函数,用于注册命令
const registerCommand = (command: string, callback: (...args: any[]) => any, thisArg?: any) =>
subscribe(vscode.commands.registerCommand(command, callback, thisArg));
// 注册一个文件系统提供程序,用于处理 ssh 协议的文件系统
subscribe(vscode.workspace.registerFileSystemProvider('ssh', new FileSystemRouter(manager), { isCaseSensitive: true }));
// 注册一个树视图,用于展示 sshfs 配置
subscribe(vscode.window.createTreeView('sshfs-configs', { treeDataProvider: new ConfigTreeProvider(), showCollapseAll: true }));
// 创建一个 ConnectionTreeProvider 实例,用于展示连接信息
const connectionTreeProvider = new ConnectionTreeProvider(manager.connectionManager);
// 注册一个树视图,用于展示 sshfs 连接
subscribe(vscode.window.createTreeView('sshfs-connections', { treeDataProvider: connectionTreeProvider, showCollapseAll: true }));
// 注册一个任务提供程序,用于处理 ssh 任务
subscribe(vscode.tasks.registerTaskProvider('ssh-shell', manager));
// 注册一个终端链接提供程序
subscribe(vscode.window.registerTerminalLinkProvider(manager));
// 设置条件语句的上下文
setupWhenClauseContexts(manager.connectionManager);
/**
*
* @param name -
* @param handler -
* @returns
*/
function registerCommandHandler(name: string, handler: CommandHandler) {
/**
*
* @param arg - SSH URI
* @returns
*/
const callback = async (arg?: string | FileSystemConfig | Connection | SSHPseudoTerminal | vscode.Uri) => {
// 如果存在 promptOptions 并且输入参数为空或为字符串
if (handler.promptOptions && (!arg || typeof arg === 'string')) {
// 使用 pickComplex 函数从管理器中选择一个复杂的对象,并将其赋值给 arg
arg = await pickComplex(manager, {...handler.promptOptions, nameFilter: arg });
}
// 如果输入参数是字符串,则调用 handleString 方法处理
if (typeof arg === 'string') return handler.handleString?.(arg);
// 如果输入参数为空,则直接返回
if (!arg) return;
// 如果输入参数是 URI 类型,则调用 handleUri 方法处理
if (arg instanceof vscode.Uri) {
return handler.handleUri?.(arg);
} else if ('handleInput' in arg) {
}
// 如果输入参数存在 handleInput 属性,则调用 handleTerminal 方法处理
else if ('handleInput' in arg) {
return handler.handleTerminal?.(arg);
} else if ('client' in arg) {
}
// 如果输入参数存在 client 属性,则调用 handleConnection 方法处理
else if ('client' in arg) {
return handler.handleConnection?.(arg);
} else if ('name' in arg) {
}
// 如果输入参数存在 name 属性,则调用 handleConfig 方法处理
else if ('name' in arg) {
return handler.handleConfig?.(arg);
}
// 如果以上条件都不满足,则记录一条警告信息
Logging.warning(`CommandHandler for '${name}' could not handle input '${arg}'`);
};
// 注册命令
registerCommand(name, callback);
}
/**
*
* manager.openSettings { type: 'newconfig' }
*/
// sshfs.new()
registerCommand('sshfs.new', () => manager.openSettings({ type: 'newconfig' }));
/**
*
* @param name -
* @param handler -
* @returns
*/
// sshfs.add(target?: string | FileSystemConfig)
registerCommandHandler('sshfs.add', {
/**
*
* promptConfigs: true
* promptConnections: true
* promptInstantConnection: true
*/
promptOptions: { promptConfigs: true, promptConnections: true, promptInstantConnection: true },
/**
*
* @param config -
* @returns
*/
handleConfig: config => manager.commandConnect(config),
});
/**
* SSHFS
* @param name -
* @param handler -
* @returns
*/
// sshfs.disconnect(target: string | FileSystemConfig | Connection)
registerCommandHandler('sshfs.disconnect', {
/**
*
* promptConnections: true
*/
promptOptions: { promptConnections: true },
/**
*
* @param name -
* @returns
*/
handleString: name => manager.commandDisconnect(name),
/**
*
* @param config -
* @returns
*/
handleConfig: config => manager.commandDisconnect(config.name),
/**
*
* @param con -
* @returns
*/
handleConnection: con => manager.commandDisconnect(con),
});
/**
* SSHFS
* manager.connectionManager.closeConnection
*/
// sshfs.disconnectAll()
registerCommand('sshfs.disconnectAll', () => {
const conns = manager.connectionManager;
// 遍历所有的活动连接,并调用 closeConnection 方法关闭它们
// Does not close pending connections (yet?)
conns.getActiveConnections().forEach(conn => conns.closeConnection(conn, 'command:disconnectAll'));
});
// sshfs.terminal(target?: FileSystemConfig | Connection | vscode.Uri)
registerCommandHandler('sshfs.terminal', {
/**
*
* promptConfigs: true
* promptConnections: true
* promptInstantConnection: true
*/
promptOptions: { promptConfigs: true, promptConnections: true, promptInstantConnection: true },
/**
*
* @param config -
* @returns
*/
handleConfig: config => manager.commandTerminal(config),
/**
*
* @param con -
* @returns
*/
handleConnection: con => manager.commandTerminal(con),
/**
* URI
* @param uri - URI
* @returns
*/
handleUri: async uri => {
// 根据 URI 的 authority 部分选择连接
const con = await pickConnection(manager, uri.authority);
// 如果找到了连接,则打开终端
con && manager.commandTerminal(con, uri);
},
});
/**
* SSHFS
* @param name -
* @param handler -
* @returns
*/
// sshfs.focusTerminal(target?: SSHPseudoTerminal)
registerCommandHandler('sshfs.focusTerminal', {
/**
*
* promptTerminals: true
*/
promptOptions: { promptTerminals: true },
/**
*
* @param terminal -
* @returns
*/
handleTerminal: ({ terminal }) => terminal?.show(false),
});
/**
* SSHFS
* @param name -
* @param handler -
* @returns
*/
// sshfs.closeTerminal(target?: SSHPseudoTerminal)
registerCommandHandler('sshfs.closeTerminal', {
/**
*
* promptTerminals: true
*/
promptOptions: { promptTerminals: true },
/**
*
* @param terminal -
* @returns
*/
handleTerminal: terminal => terminal.close(),
});
/**
* SSHFS
* @param name -
* @param handler -
* @returns
*/
// sshfs.configure(target?: string | FileSystemConfig)
registerCommandHandler('sshfs.configure', {
/**
*
* promptConfigs: true
*/
promptOptions: { promptConfigs: true },
/**
*
* @param config -
* @returns
*/
handleConfig: config => manager.commandConfigure(config),
});
/**
*
* loadConfigs
*/
// sshfs.reload()
registerCommand('sshfs.reload', loadConfigs);
/**
*
* manager.openSettings
*/
// sshfs.settings()
registerCommand('sshfs.settings', () => manager.openSettings());
/**
*
* connectionTreeProvider.refresh()
*/
// sshfs.refresh()
registerCommand('sshfs.refresh', () => connectionTreeProvider.refresh());
/**
* onConnectionAdded
* @param con -
*/
subscribe(manager.connectionManager.onConnectionAdded(async con => {
// 当有新连接添加时,重新加载与该连接名称相关的工作区文件夹配置
await reloadWorkspaceFolderConfigs(con.actualConfig.name);
}));
}

Loading…
Cancel
Save