Skip to content

feat: add mcpp.newProject command to scaffold and open projects - #3

Merged
wellwei merged 5 commits into
mcpp-community:mainfrom
Ximiaw:feat/new-project
Aug 8, 2026
Merged

feat: add mcpp.newProject command to scaffold and open projects#3
wellwei merged 5 commits into
mcpp-community:mainfrom
Ximiaw:feat/new-project

Conversation

@Ximiaw

@Ximiaw Ximiaw commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

功能

新增 mcpp.newProject 命令(命令面板「mcpp: 新建工程」),在 VS Code 内完成新项目脚手架:

  1. 输入项目名(校验非空、不含路径分隔符)
  2. 选择项目位置
  3. 模态确认后,在所选位置执行 mcpp new <项目名>,创建同名项目文件夹
  4. 成功后打开新项目文件夹,并在新窗口中自动执行 mcpp.refreshCompilationDatabase,完成首次构建与 clangd 配置

实现说明

  • 命令注册在 McppCliController,复用 runProcessmcpp.path 设置,受工作区信任约束;失败时提示并将日志保留在 mcpp 输出频道
  • vscode.openFolder 会重载窗口,刷新请求通过 globalStatePENDING_NEW_PROJECT_KEY)传递到新窗口,activate 时核对项目路径后兑现,且只兑现一次
  • 刷新以后台方式触发(void),不阻塞 activate()——否则扩展激活期间命令会排队,表现为编辑器标题按钮点击无反应

测试

  • 更新 commands.test.tsartifacts.test.ts 的命令清单断言
  • 新增两个结构测试:确认步骤在创建之前、globalState 标记在打开文件夹之前写入;activate 中刷新为非阻塞调用
  • npm test:97 个测试全部通过

@wellwei

wellwei commented Aug 7, 2026

Copy link
Copy Markdown
Member

维护者结论:功能方向可行,mcpp.newProject 也符合扩展当前的职责边界;但当前实现存在以下合入阻塞问题,暂不合并,请修复后再复核。

  1. 项目名可能被 mcpp 解析为 CLI 选项。 当前只拒绝空值和路径分隔符,随后直接执行 mcpp new <projectName>。例如以 - 开头的输入可能命中 --template--list-templates 等选项;进程甚至可能成功退出,但没有创建目标工程。这不是 shell 注入,参数数组也不能阻止 CLI 自身解析选项。至少应拒绝 - 前缀、...,并明确处理目标路径已存在的情况。

  2. pending 刷新状态可能被错误窗口提前消费。 PENDING_NEW_PROJECT_KEY 存在 globalState 中,但 activate 时在核对工程路径之前就清除了它。任一同时激活的 VS Code 窗口都可能先删除该状态,真正的新工程窗口随后无法刷新。必须先匹配目标工程,再只消费属于该窗口/本次操作的记录;建议记录目标路径和唯一 token,并考虑过期时间。

  3. 打开文件夹失败会遗留 pending 状态。 当前先写 globalState,再调用 vscode.openFolder;如果打开失败,本次状态没有按 token 清理,之后打开同一路径可能意外触发完整构建。

  4. 需要明确创建后的行为边界。 当前设计在新窗口自动执行完整 mcpp build。后续 #5 会在缺少 CDB 时执行 IDE configure,因此这里需要明确产品契约是“创建并打开工程”,还是“创建后立即完整构建”,避免未来重复执行 IDE configure 和 build。新窗口仍必须以它自己的 workspace trust 为执行前提。

  5. 现有新增测试只是源码字符串和调用顺序断言。 请补行为级覆盖:非法项目名、错误窗口不消费 pending、目标窗口只消费一次、openFolder 失败清理,以及新窗口未受信任时不执行构建。

我在该提交上独立复核了 npm test,结果为 97/97;但上述行为均不在当前测试覆盖范围内。

@Ximiaw

Ximiaw commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

已按复核意见修改并推送(d8db658),请复核:

  1. 项目名校验:提取为 src/newProject.tsvalidateNewProjectName 纯函数——拒绝空值、路径分隔符、- 前缀(防止被 mcpp 解析为 --template/--list-templates 等选项)、...;选定位置后先 existsSync 检查目标路径,已存在则直接报错返回,不再进入确认步骤。

2./3. pending 状态问题:产品契约改为"创建并打开"(见第 4 点)后,globalState pending 机制已整体移除,extension.ts 完全还原——错误窗口消费、openFolder 失败遗留状态两类问题随之消除。

  1. 行为契约:明确为"创建并打开工程"——成功后仅 vscode.openFolder,不自动执行 build,避免与 feat: integrate mcpp build --configure-only into clangd workflow #5 缺少 CDB 时的 IDE configure 重复执行;新窗口的 clangd 配置仍走 activate 的原有 reconcile 流程,以其自身 workspace trust 为执行前提。契约已写入 cliController.newProject 注释。

  2. 行为级测试:新增 test/newProject.test.ts,覆盖空值/纯空白、路径分隔符、- 选项前缀、./..、合法名(含前后空白)共 5 组;artifacts.test.ts 结构测试重写为锁定"检查已存在 → 确认 → 创建 → 打开"的顺序,并新增契约断言(controller/extension 中无 globalState/PENDING_NEW_PROJECT 残留,防回归)。

npm test:102/102 通过。

@Sunrisepeak
Sunrisepeak requested a review from wellwei August 7, 2026 14:29
@wellwei

wellwei commented Aug 8, 2026

Copy link
Copy Markdown
Member

复核了 d8db658。前一轮的主要产品问题已经正确收敛:

但当前仍有一个合入阻塞:项目名可以破坏 mcpp 生成的工程内容。

validateNewProjectName() 目前接受双引号和控制字符。例如 bad"name 会通过校验。mcpp 当前会:

  1. default_template(name) 中直接生成 name = "{}",没有 TOML 转义;
  2. src/main.cpp 模板中把 PROJECT 直接替换为项目名,没有 C++ 字符串转义。

因此该输入可能让 mcpp new 成功创建目录,却同时生成无效的 mcpp.toml 和 C++ 源码。请至少拒绝:

  • "
  • C0/DEL 控制字符(U+0000..U+001FU+007F

并补充对应单测。Windows 的保留字符、保留设备名和尾随点/空格也建议按跨平台项目名策略一并处理;根本修复最终还应落在 mcpp CLI 自身,但扩展不能主动接受已知会生成坏工程的名称。

测试方面,我在隔离快照上复核了 npm test,结果为 102/102。不过 artifacts.test.ts 目前验证的是源码字符串出现顺序,并没有真正执行“目标已存在时不确认/不创建”“创建失败不打开”“成功后只打开”等控制流,不应称为行为级覆盖。名称校验缺陷是当前阻塞;控制器行为测试至少应作为明确的后续测试债务,最好通过提取可注入依赖的流程函数补齐。

修正项目名边界后,#3 可以独立于 #5 和上游 configure-only PR 合入。

@wellwei wellwei added the enhancement New feature or request label Aug 8, 2026
@Ximiaw

Ximiaw commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

已按复核意见完成修复并推送(c239dc0、3aa5ca0),请复核:

  1. 项目名边界validateNewProjectName 新增拒绝 " 和 C0/DEL 控制字符(U+0000..U+001F、U+007F),防止 bad"name 这类输入让 mcpp 无转义地生成无效的 mcpp.toml / main.cpp;并按跨平台策略一并拒绝 Windows 保留字符 <>:"|?*、保留设备名(CON/PRN/AUX/NUL/COM1-9/LPT1-9)和尾随 .(尾随空格在 trim 阶段已消除)。注释中已注明根本修复应落在 mcpp CLI 自身的模板转义。对应单测新增两组:引号/控制字符 6 例,Windows 保留字符/设备名/尾随点 15 例;并以 consolecom10 确认不误伤合法名。

  2. 控制器行为测试(测试债务)newProject() 流程已提取为 src/newProject.tsrunNewProjectFlow,依赖(exists/confirm/run/openFolder/showError)全部注入;test/newProject.test.ts 新增 4 个行为级测试,用调用日志断言完整控制流——"目标已存在→不确认/不创建/不打开""取消确认→不创建/不打开""创建失败→报错/不打开""成功→只打开项目文件夹(不自动构建)"。artifacts.test.ts 的原字符串顺序断言保留为"控制器正确注入依赖"的薄检查,注释已指向行为测试。

npm test:108/108 通过。

@wellwei

wellwei commented Aug 8, 2026

Copy link
Copy Markdown
Member

已完成本轮复核发现的两项修复并推送(bfbaffe):

  • 拒绝名称中包含当前 mcpp 内置模板标记 PROJECT,避免 mcpp new 无限替换并使扩展无期限等待;
  • Windows 保留设备名校验覆盖带扩展形式,如 CON.txtAUX.mdLPT1.log

两项均先补回归测试并确认旧实现失败,再完成修复。完整 npm test 结果为 110/110

mcpp CLI 的根本问题(统一名称契约、路径越界、模板替换/转义和写入错误检查)已单独记录在 mcpp-community/mcpp#380;扩展侧当前修复是发布上游修复前的必要防线。

@wellwei
wellwei merged commit 694acd8 into mcpp-community:main Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants