refactor🎨: (阅读代码):config.ts增加注释

master
yetao 3 weeks ago
parent 9266c7dcae
commit 34c335313e

@ -1,108 +1,221 @@
// 引入 common/fileSystemConfig 模块中的 ConfigLocation、FileSystemConfig、invalidConfigName、isFileSystemConfig、parseConnectionString 类型或函数
import { ConfigLocation, FileSystemConfig, invalidConfigName, isFileSystemConfig, parseConnectionString } from 'common/fileSystemConfig'; import { ConfigLocation, FileSystemConfig, invalidConfigName, isFileSystemConfig, parseConnectionString } from 'common/fileSystemConfig';
// 引入 jsonc-parser 模块中的 ParseError、parse as parseJsonc、printParseErrorCode 类型或函数
import { ParseError, parse as parseJsonc, printParseErrorCode } from 'jsonc-parser'; import { ParseError, parse as parseJsonc, printParseErrorCode } from 'jsonc-parser';
// 引入 path 模块,用于处理和转换文件路径
import * as path from 'path'; import * as path from 'path';
// 引入 vscode 模块,用于访问 VS Code 的 API
import * as vscode from 'vscode'; import * as vscode from 'vscode';
// 引入 extension 模块中的 MANAGER 变量
import { MANAGER } from './extension'; import { MANAGER } from './extension';
// 引入 logging 模块中的 Logging、OUTPUT_CHANNEL 类型或函数
import { Logging, OUTPUT_CHANNEL } from './logging'; import { Logging, OUTPUT_CHANNEL } from './logging';
// 引入 utils 模块中的 catchingPromise 函数
import { catchingPromise } from './utils'; import { catchingPromise } from './utils';
// 定义一个常量 fs它引用了 VS Code 工作区的文件系统 API
const fs = vscode.workspace.fs; const fs = vscode.workspace.fs;
// Logger scope with default warning/error options (which enables stacktraces) disabled // Logger scope with default warning/error options (which enables stacktraces) disabled
// 创建一个日志记录器,范围为 undefined禁用堆栈跟踪
const logging = Logging.scope(undefined, false); const logging = Logging.scope(undefined, false);
// 禁用警告的默认选项
logging.warning.options = {}; logging.warning.options = {};
// 禁用错误的默认选项
logging.error.options = {}; logging.error.options = {};
/**
*
*
* @param configs -
* @param index - 0
* @returns
*/
function randomAvailableName(configs: FileSystemConfig[], index = 0): [string, number] { function randomAvailableName(configs: FileSystemConfig[], index = 0): [string, number] {
// 初始化名称为 'unnamed' 或 'unnamed' 加上索引
let name = index ? `unnamed${index}` : 'unnamed'; let name = index ? `unnamed${index}` : 'unnamed';
// 当名称在配置数组中存在时,进入循环
while (configs.find(c => c.name === name)) { while (configs.find(c => c.name === name)) {
// 索引加一
index += 1; index += 1;
// 更新名称为 'unnamed' 加上新的索引
name = `unnamed${index}`; name = `unnamed${index}`;
} }
// 返回随机可用名称和下一个索引
return [name, index + 1]; return [name, index + 1];
} }
// TODO: Do this better, especially since we can dynamically start adding configs (for workspaceFolders) // TODO: Do this better, especially since we can dynamically start adding configs (for workspaceFolders)
/**
*
*
*
*
* @returns {Promise<void>} Promise
*/
export async function renameNameless() { export async function renameNameless() {
// 获取 sshfs 配置对象
const conf = vscode.workspace.getConfiguration('sshfs'); const conf = vscode.workspace.getConfiguration('sshfs');
// 检查 configs 配置项,获取其全局、工作区和工作区文件夹级别的值
const inspect = conf.inspect<FileSystemConfig[]>('configs')!; const inspect = conf.inspect<FileSystemConfig[]>('configs')!;
// 初始化随机索引
let randomIndex = 0; let randomIndex = 0;
// 收集所有级别的配置
const configs = [ const configs = [
...(inspect.globalValue || []), ...(inspect.globalValue || []),
...(inspect.workspaceValue || []), ...(inspect.workspaceValue || []),
...(inspect.workspaceFolderValue || []), ...(inspect.workspaceFolderValue || []),
]; ];
/**
*
* @param {FileSystemConfig[] | undefined} v -
* @param {vscode.ConfigurationTarget} loc -
* @returns {Promise<void>} - Promise
*/
function patch(v: FileSystemConfig[] | undefined, loc: vscode.ConfigurationTarget) { function patch(v: FileSystemConfig[] | undefined, loc: vscode.ConfigurationTarget) {
// 如果配置数组不存在,则不进行任何操作
if (!v) return; if (!v) return;
// 标记是否所有配置都有名称
let okay = true; let okay = true;
// 遍历配置数组
v.forEach((config) => { v.forEach((config) => {
// 如果配置没有名称
if (!config.name) { if (!config.name) {
// 生成一个随机可用名称
[config.name, randomIndex] = randomAvailableName(configs, randomIndex); [config.name, randomIndex] = randomAvailableName(configs, randomIndex);
// 记录警告信息
logging.warning(`Renamed unnamed config to ${config.name}`); logging.warning(`Renamed unnamed config to ${config.name}`);
// 标记配置需要更新
okay = false; okay = false;
} }
}); });
// 如果所有配置都有名称,则不进行任何操作
if (okay) return; if (okay) return;
// 更新配置
return conf.update('configs', v, loc).then(() => { }, res => logging.error`Error while saving configs (CT=${loc}): ${res}`); return conf.update('configs', v, loc).then(() => { }, res => logging.error`Error while saving configs (CT=${loc}): ${res}`);
} }
// 依次更新全局、工作区和工作区文件夹级别的配置
await patch(inspect.globalValue, vscode.ConfigurationTarget.Global); await patch(inspect.globalValue, vscode.ConfigurationTarget.Global);
await patch(inspect.workspaceValue, vscode.ConfigurationTarget.Workspace); await patch(inspect.workspaceValue, vscode.ConfigurationTarget.Workspace);
await patch(inspect.workspaceFolderValue, vscode.ConfigurationTarget.WorkspaceFolder); await patch(inspect.workspaceFolderValue, vscode.ConfigurationTarget.WorkspaceFolder);
} }
// 定义一个数组,用于存储已加载的文件系统配置
let loadedConfigs: FileSystemConfig[] = []; let loadedConfigs: FileSystemConfig[] = [];
/**
*
* @returns {FileSystemConfig[]}
*/
export function getConfigs() { export function getConfigs() {
// 返回已加载的文件系统配置
return loadedConfigs; return loadedConfigs;
} }
/**
*
*
*/
export const UPDATE_LISTENERS: ((configs: FileSystemConfig[]) => any)[] = []; export const UPDATE_LISTENERS: ((configs: FileSystemConfig[]) => any)[] = [];
/**
*
* @param file - URI
* @param quiet - true
* @returns undefined
*/
async function readConfigFile(file: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> { async function readConfigFile(file: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> {
// 尝试读取文件内容,如果失败则返回错误
const content = await fs.readFile(file).then<Uint8Array | NodeJS.ErrnoException>(v => v, e => e); const content = await fs.readFile(file).then<Uint8Array | NodeJS.ErrnoException>(v => v, e => e);
// 如果读取失败且错误代码为 'ENOENT'(文件未找到),并且 quiet 为 true则返回 undefined
if (content instanceof Error) { if (content instanceof Error) {
if (content.code === 'ENOENT' && quiet) return undefined; if (content.code === 'ENOENT' && quiet) return undefined;
// 记录错误信息
logging.error`Error while reading config file ${file}: ${content}`; logging.error`Error while reading config file ${file}: ${content}`;
return undefined; return undefined;
} }
// 存储解析过程中出现的错误
const errors: ParseError[] = []; const errors: ParseError[] = [];
// 尝试解析文件内容为 JSON如果失败则返回 null
const parsed: FileSystemConfig[] | null = parseJsonc(Buffer.from(content.buffer).toString(), errors); const parsed: FileSystemConfig[] | null = parseJsonc(Buffer.from(content.buffer).toString(), errors);
// 如果解析失败或存在错误,则记录错误信息并返回空数组
if (!parsed || errors.length) { if (!parsed || errors.length) {
// 格式化错误信息
const formatted = errors.map(({ error, offset, length }) => `${printParseErrorCode(error)} at ${offset}-${offset + length}`); const formatted = errors.map(({ error, offset, length }) => `${printParseErrorCode(error)} at ${offset}-${offset + length}`);
// 记录错误信息
logging.error`Couldn't parse ${file} due to invalid JSON:\n${formatted.join('\n')}`; logging.error`Couldn't parse ${file} due to invalid JSON:\n${formatted.join('\n')}`;
// 显示错误信息给用户
vscode.window.showErrorMessage(`Couldn't parse the SSH FS config file at ${file}, invalid JSON`); vscode.window.showErrorMessage(`Couldn't parse the SSH FS config file at ${file}, invalid JSON`);
return []; return [];
} }
// 为每个配置项添加文件位置信息
parsed.forEach(c => c._locations = [c._location = file.toString()]); parsed.forEach(c => c._locations = [c._location = file.toString()]);
// 记录调试信息
logging.debug`Read ${parsed.length} configs from ${file}`; logging.debug`Read ${parsed.length} configs from ${file}`;
// 返回解析后的配置数组
return parsed; return parsed;
} }
/**
*
* @param uri - URI
* @param quiet - true
* @returns undefined
*/
async function readConfigDirectory(uri: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> { async function readConfigDirectory(uri: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> {
// 获取目录的状态,如果失败则返回 undefined
const stat = await fs.stat(uri).then(e => e, () => undefined); const stat = await fs.stat(uri).then(e => e, () => undefined);
if (!stat) return undefined; if (!stat) return undefined;
// 读取目录下的所有文件和目录,如果不是目录则会出错
const files = await fs.readDirectory(uri); // errors if not a directory const files = await fs.readDirectory(uri); // errors if not a directory
logging.debug`readConfigDirectory got files: ${files}`; logging.debug`readConfigDirectory got files: ${files}`;
// 过滤出文件类型的项,并筛选出以.json 或.jsonc 结尾的文件
const parsed = await Promise.all(files const parsed = await Promise.all(files
.filter(([, t]) => t & vscode.FileType.File).map(([f]) => f) .filter(([, t]) => t & vscode.FileType.File).map(([f]) => f)
.filter(file => file.endsWith('.json') || file.endsWith('.jsonc')) .filter(file => file.endsWith('.json') || file.endsWith('.jsonc'))
// 读取每个配置文件,并将结果存储在 parsed 数组中
.map(file => readConfigFile(vscode.Uri.joinPath(uri, file), quiet))); .map(file => readConfigFile(vscode.Uri.joinPath(uri, file), quiet)));
// 如果 parsed 数组中有任何元素,则返回过滤后的数组,否则返回 undefined
return parsed.some(Boolean) ? parsed.filter(Array.isArray).flat() : undefined; return parsed.some(Boolean) ? parsed.filter(Array.isArray).flat() : undefined;
} }
/**
* URI SSH
* @param uri - URI
* @returns URI 'ssh' true false
*/
const skipDisconnectedUri = (uri: vscode.Uri) => uri.scheme === 'ssh' &&!MANAGER?.connectionManager.getActiveConnection(uri.authority); const skipDisconnectedUri = (uri: vscode.Uri) => uri.scheme === 'ssh' &&!MANAGER?.connectionManager.getActiveConnection(uri.authority);
/**
* URI URI
* URI URI
* /
*
* @param uri - URI
* @param quiet - true
* @returns URI undefined
*/
async function findConfigs(uri: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> { async function findConfigs(uri: vscode.Uri, quiet: boolean): Promise<FileSystemConfig[] | undefined> {
// 检查 URI 的方案是否为 'ssh'
if (uri.scheme === 'ssh') { if (uri.scheme === 'ssh') {
// Ignore SSH URIs for connections that are still connecting // Ignore SSH URIs for connections that are still connecting
// 忽略那些连接仍在进行中的 SSH URI
if (skipDisconnectedUri(uri)) { if (skipDisconnectedUri(uri)) {
// 记录一条调试信息,表明正在跳过配置文件
logging.debug`Skipping config file '${uri}' for disconnected config`; logging.debug`Skipping config file '${uri}' for disconnected config`;
// 返回一个空数组,表示没有找到配置
return []; return [];
} }
} }
try { try {
// 尝试读取配置目录。
return await readConfigDirectory(uri, quiet); return await readConfigDirectory(uri, quiet);
} catch { } catch {
// 如果读取配置目录失败,则捕获错误。
// 并且尝试读取配置文件来代替。
return await readConfigFile(uri, quiet); return await readConfigFile(uri, quiet);
} }
} }
@ -114,6 +227,17 @@ async function findConfigs(uri: vscode.Uri, quiet: boolean): Promise<FileSystemC
* Will return `undefined` if the given file doesn't exist, or lead to a directory with no readable config files. * Will return `undefined` if the given file doesn't exist, or lead to a directory with no readable config files.
* Will return an empty array if the given path is a relative path. * Will return an empty array if the given path is a relative path.
*/ */
/**
*
*
* /
*
* undefined
*
* @param location - vscode.Uri
* @param quiet - true
* @returns
*/
async function findConfigFiles(location: string | vscode.Uri, quiet = false): Promise<[configs: FileSystemConfig[] | undefined, isAbsolute: boolean]> { async function findConfigFiles(location: string | vscode.Uri, quiet = false): Promise<[configs: FileSystemConfig[] | undefined, isAbsolute: boolean]> {
if (location instanceof vscode.Uri) { if (location instanceof vscode.Uri) {
return [await findConfigs(location, quiet), true]; return [await findConfigs(location, quiet), true];

Loading…
Cancel
Save