VSCode自定义语言扩展:实现TypeScript式文件重命名引用更新体验
实现自定义语言的文件重命名引用更新体验
不需要手动监听onDidRenameFiles做弹窗,VS Code有原生的优雅机制可以实现和TypeScript一致的体验,核心是利用workspace.onWillRenameFiles事件结合工作区编辑能力:
优先使用
onWillRenameFiles前置钩子
这个事件在文件实际重命名前触发,你可以在这里计算所有需要更新的引用位置,生成WorkspaceEdit对象返回给VS Code。VS Code会自动弹出确认提示,让用户预览并决定是否应用所有引用变更,完全复用原生交互逻辑(包括撤销、批量变更预览),和TypeScript的体验一致。结合已有语言服务能力
如果你的自定义语言已经实现了RenameProvider来处理符号重命名,可以把文件路径变更关联到符号重命名的逻辑里,复用已有的引用查找和替换能力,减少重复代码。不推荐
onDidRenameFiles的原因
这个事件是文件重命名后触发的,属于事后修改引用,不仅用户体验差(文件已经改名再改引用),还需要自己处理弹窗、撤销、冲突等问题,远不如原生前置钩子的方案可靠。
简单实现示例
import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.workspace.onWillRenameFiles(async (event) => { // 筛选自定义语言文件(示例后缀为.myLang) const targetFile = event.files.find(f => f.newUri.fsPath.endsWith('.myLang')); if (!targetFile) return; const workspaceEdit = new vscode.WorkspaceEdit(); const oldFileName = targetFile.oldUri.path.split('/').pop()!; const newFileName = targetFile.newUri.path.split('/').pop()!; // 查找工作区内所有自定义语言文件 const allLangFiles = await vscode.workspace.findFiles('**/*.myLang'); for (const file of allLangFiles) { const doc = await vscode.workspace.openTextDocument(file); const text = doc.getText(); // 匹配引用旧文件名的模式(根据你的语言语法调整) const refRegex = new RegExp(`import\\s*['"]\\.\\/${oldFileName}['"]`, 'g'); let match; while ((match = refRegex.exec(text)) !== null) { const range = new vscode.Range( doc.positionAt(match.index), doc.positionAt(match.index + match[0].length) ); workspaceEdit.replace(file, range, `import './${newFileName}'`); } } // 提交编辑操作,VS Code自动处理用户确认流程 event.waitUntil(Promise.resolve(workspaceEdit)); }) ); }
内容的提问来源于stack exchange,提问作者Vincent den Boer
相关产品推荐
相关产品推荐

