Snippet 修改对 VSCode Extension 的影响分析
你的问题
"这样的修改,会影响通过vscode生成的文件,名字不会正常替换吗?"
简短回答
不会影响! ✅
我已经修改了 renderSnippet 函数,让它同时支持两种语法:
- 旧语法(用于程序化生成)${1:Name}- 新语法(用于手动输入 snippet)
详细说明
两种使用场景
场景 1: 手动输入 Snippet (在编辑器中)
使用方式:
- 在
.dart文件中输入stWidget - 按
Tab键触发 - 交互式输入参数
使用的语法: ${1:Name} (VSCode 标准 tabstop)
处理方式: VSCode 自动处理,不经过我们的代码
我的修改: ✅ 已修复,现在支持参数输入
场景 2: 通过命令生成文件 (VSCode Extension)
使用方式:
- 右键点击文件夹
- 选择
Flu: Generate - 选择类型和输入名称
- 自动生成文件
使用的语法: 或 ${1:Name} (两种都支持)
处理方式: 通过 renderSnippet 函数替换
我的修改: ✅ 增强了 renderSnippet,同时支持两种语法
代码流程
用户执行命令: Flu: Generate
↓
输入名称: "MyButton"
↓
调用: generateWidget("MyButton", options)
↓
读取 snippet: getSnippetContent(projectDir, 'flu.stWidget', { Name: 'MyButton' })
↓
调用: renderSnippet(snippetBody, { Name: 'MyButton' })
↓
替换占位符:
- {{Name}} → MyButton ✅
- ${1:Name} → MyButton ✅
↓
写入文件: my_button_widget.dartrenderSnippet 函数的增强
之前的代码:
typescript
export function renderSnippet (bodyLines: string[] | string, variables: Record<string, any>): string {
const body = Array.isArray(bodyLines) ? bodyLines.join('\n') : String(bodyLines || '');
// 只支持 {{Name}} 语法
return body.replace(/\{\{(\w+)\}\}/g, (_: string, key: string) => {
return Object.prototype.hasOwnProperty.call(variables, key) ? String(variables[key]) : `{{${key}}}`;
});
}现在的代码:
typescript
export function renderSnippet (bodyLines: string[] | string, variables: Record<string, any>): string {
const body = Array.isArray(bodyLines) ? bodyLines.join('\n') : String(bodyLines || '');
// 1. 替换 {{Name}} 格式的占位符(旧语法,保持兼容)
let result = body.replace(/\{\{(\w+)\}\}/g, (_: string, key: string) => {
return Object.prototype.hasOwnProperty.call(variables, key) ? String(variables[key]) : `{{${key}}}`;
});
// 2. 替换 ${1:Name} 格式的 VSCode tabstop(新语法)
result = result.replace(/\$\{(\d+):([^}]+)\}/g, (_match: string, _tabstopNum: string, defaultValue: string) => {
const varMatch = defaultValue.match(/^(\w+)$/);
if (varMatch) {
const varName = varMatch[1];
return Object.prototype.hasOwnProperty.call(variables, varName) ? String(variables[varName]) : defaultValue;
}
// 处理复杂的 tabstop 转换(如 ${1/(.*)/${1:/downcase}/})
if (defaultValue.includes('${')) {
return '';
}
return defaultValue;
});
return result;
}测试结果
=== 测试 renderSnippet 函数 ===
测试 1: 旧语法 {{Name}}
class MyButtonWidget extends StatelessWidget {
const MyButtonWidget({super.key});
}
✅ 预期: MyButtonWidget
测试 2: 新语法 ${1:Name}
class MyButtonWidget extends StatelessWidget {
const MyButtonWidget({super.key});
}
✅ 预期: MyButtonWidget
测试 3: 混合语法
class MyButtonWidget extends StatelessWidget {
/// Title: My Button
const MyButtonWidget({super.key});
}
✅ 预期: MyButtonWidget 和 My Button
测试 5: 默认值(没有提供变量)
class MyButtonWidget extends StatelessWidget {
String get title => 'Title';
}
✅ 预期: Name 被替换,Title 保留默认值
=== 所有测试完成 ===实际使用对比
通过命令生成 Widget
操作步骤:
- 右键点击
lib/widgets文件夹 - 选择
Flu: Generate - 选择
Widget - 选择
Stateless - 输入名称:
my_button
生成的文件: lib/widgets/my_button_widget.dart
文件内容:
dart
import 'package:flutter/material.dart';
class MyButtonWidget extends StatelessWidget {
// ------------------------------
// 1. 外部配置参数(构造函数)
// ------------------------------
/// 构造函数
const MyButtonWidget({super.key});
// ------------------------------
// 2. UI构建(核心:根据参数渲染)
// ------------------------------
@override
Widget build(BuildContext context) {
Widget w = const SizedBox.shrink();
w = Padding(padding: const EdgeInsets.all(12), child: w);
return w;
}
// ------------------------------
// 3. 辅助方法(UI计算/转换)
// ------------------------------
String _format(String s) => s;
}结果: ✅ 名称正确替换为 MyButton
手动输入 Snippet
操作步骤:
- 打开任意
.dart文件 - 输入
lessWidget - 按
Tab - 输入
MyButton - 按
Tab跳过其他参数
结果: ✅ 同样生成正确的代码
兼容性保证
向后兼容
- ✅ 旧的
语法继续工作 - ✅ 现有的项目不受影响
- ✅ 之前创建的 snippet 文件仍然有效
向前兼容
- ✅ 新的
${1:Name}语法支持交互式输入 - ✅ 通过命令生成文件时也能正确替换
- ✅ 两种语法可以混用
总结
问题
你担心修改 snippet 语法后,通过 VSCode Extension 命令生成文件时,名字不能正常替换。
答案
不会有问题! 因为:
- 我修改了
renderSnippet函数,让它同时支持两种语法 - 测试验证通过,两种语法都能正确替换
- 保持向后兼容,旧的
语法继续工作 - 新增交互式支持,手动输入 snippet 时可以填写参数
两种语法的用途
| 语法 | 用途 | 处理方式 |
|---|---|---|
| 程序化生成(命令) | renderSnippet 函数替换 |
${1:Name} | 交互式输入(手动) | VSCode 自动处理 + renderSnippet 函数替换 |
最终效果
无论是:
- ✅ 通过命令生成文件 (
Flu: Generate) - ✅ 手动输入 snippet (
stWidget+ Tab)
都能正确工作,名字都会被正确替换!
修改文件:
packages/core/src/utils/snippet_loader.ts- 增强renderSnippet函数packages/vscode-extension/snippets/dart.code-snippets- 更新为新语法packages/core/templates/snippets/dart.code-snippets- 同步更新packages/v2/templates/snippets/dart.code-snippets- 同步更新
测试文件:
packages/core/test/test_snippet_render.js- 验证两种语法都能正确工作