CodePlanet Platform

CodePlanet 软件帮助

在页面内直接阅读项目文档,支持目录导航与原文下载。

CodePlanet 开发指南

下载原文

CodePlanet 开发指南

> Cursor 同步:本指南副本位于 [.cursor/开发指南.md](../.cursor/开发指南.md),并由 [.cursor/rules/](../.cursor/rules/) 在会话中自动注入。 > 项目约定:后续开发须持续保持 .cursor/docs/ 内容一致(见 [.cursor/README.md](../.cursor/README.md))。

平台终点(北极星):视觉检测全栈演进路线见 [docs/项目目标与架构终点.md](项目目标与架构终点.md)(Ops / Runtime / 插件 / yslib / VisionObject)。

R0 平台契约(已交付)

  • yslib Schema:[docs/schemas/yslib-v1.schema.json](schemas/yslib-v1.schema.json);示例项目 [examples/projects/demo/](../examples/projects/demo/)
  • 更新 manifest Schema(草案):[docs/schemas/update-manifest-v1.schema.json](schemas/update-manifest-v1.schema.json)
  • ProjectValidatorsrc/core/project/ProjectValidator.* — Ops 打开 .yslibCtrl+B 校验;Launcher 预检复用同一 API(R1.5)
  • AppPaths 扩展userRoot()userConfigDir()projectsRoot()launcherLogPath()runtimeDumpPath()projectLogsDir()dataDir() 固定为 %LOCALAPPDATA%/CodePlanet/(Qt GenericDataLocation,三端共用)
  • 用户数据USER/config/editor.json;出厂默认布局 resources/config/editor.default.json
  • global 关键字:Lexer/Parser 语法占位(R1 迁移 static 语义)
  • 文档:[迁移-static-global.md](迁移-static-global.md)、[附录-路径与日志约定.md](附录-路径与日志约定.md)
  • 验收 / 回归scripts/run_r0_regression.ps1(自动化 + GUI 手动清单,分工见 .cursor/开发指南.md §R0 回归约定)

R1 语义迁移(已交付)

  • ProjectGlobalStoresrc/core/project/ProjectGlobalStore.*global 跨任务存储(按 yslib 路径)
  • static:任务内持久,存于 RuntimeWorker 会话表;不再写 scope 0
  • import:Lexer/Parser + ScriptAnalyzer 静态分析;运行时链接(R2 executeImport
  • StaticMigrationAnalyzer + 迁移提示 Dock(手动扫描,见项目树右键)
  • 项目窗口USER/projects/每个子目录一个根节点(与磁盘文件夹一一对应);主 .yslib 优先 {文件夹名}.yslib,同目录多 yslib 时其余在文件树中打开
  • recent_projects + 文件 → 最近项目 + 启动选择对话框
  • YslibStructureWidget:yslib scripts + main entry 编辑;视图 → 项目结构
  • 迁移提示 Dock视图 → 迁移提示
  • 回归scripts/run_r1_regression.ps1

R1.5 Launcher v1(已交付)

  • CodePlanetr.exesrc/launcher/ — 产线启动入口(5 秒倒计时、F8 修复模式、预检、建议性更新、进程监护)
  • LauncherService:编排 ProjectValidator 预检、U 盘/在线 manifest 验签、拉起目标进程并写 launcher.log
  • UpdateManifestVerifier:RSA-SHA256 + canonical JSON 实装;公钥 resources/config/update.pub
  • ParentProcessGuard--parent-pid / --nonce 校验;CODEPLANET_DEV=1 开发豁免
  • DatabaseService::defaultProjectPath():Launcher 读取默认 yslib(app_settings.default_project_path
  • R1.5 过渡策略:优先 CodeRuntime.exe;仓库布局(检出含 CodePlanet.pro)或 CODEPLANET_DEV=1 时可回退 CodeEditor.exe
  • 回归scripts/run_r1_5_regression.ps1(分层 + Qt Test + GUI 手动清单)
  • bin 独立测试scripts/deploy_bin.ps1scripts/deploy_staging.ps1(→ dist/CodePlanet/bin)、scripts/test_parent_guard_intercept.ps1scripts/run_launcher_dev.ps1

Launcher 分层:仅依赖 src/coresrc/services 与 Qt 模块,不得 link src/gui/ / src/logic/

Launcher 链接约定(R1.5)launcher.pro 仅编入 ProjectValidator 静态分析链Lexer / Parser / ExprParser / ScriptAnalyzer),禁止编入 AstInterpreterAstRuntimeExprEvaluatorFunctionDispatcherPluginManager(完整 AST/插件运行时在 Ops/Runtime 侧)。新增 Launcher 依赖前须确认是否仅为静态预检所需。

R2 Runtime 最小闭环(已交付)

  • CodeRuntime.exesrc/runtime/ — 产线运行入口(ParentProcessGuard + --project
  • RuntimeOrchestrator + MainTaskWorker / SubTaskWorker:按 yslib tasks 调度;子任务 R2 用 simulateTrigger()
  • import 运行时AstInterpreter::executeImport 合并模块函数;静态 YS405/跨模块 call 检查
  • global 冲突ScriptAnalyzer::analyzeProjectGlobals → YS408;接入 ProjectValidator Ctrl+B
  • #include 相对路径AppPaths::resolveIncludeRelative(includeName, scriptAbsolutePath)
  • MainTaskTimerService + FunctionLib.ini timer_* API;FunctionDispatcher 内置 dispatch;子任务 YS406
  • Runtime UI:日志 / global 表 / processGroups 树(150ms 刷新);i18n:Launcher 启动时 --locale=zh_CN|en
  • 回归样例examples/projects/demoV1.1/(import + timer + global)
  • 回归scripts/run_r2_regression.ps1(分层 + Qt Test + Runtime 构建重试/日志 + 父进程拦截 + GUI 手动清单;默认 fail-fast,可选 -AllowStaleRuntime
  • bin 部署scripts/deploy_bin.ps1 含三 exe;scripts/test_runtime_parent_guard_intercept.ps1
  • 调试稳态约束(R2)AstRuntime::needsReload/loadSource 统一 CRLF/LF 后再比较源码;AstInterpreter::executeReturn 回退到最近函数帧(覆盖嵌套块 return);Debug 构建启用 assertDebugInvariants 断言暂停态栈一致性;空语句脚本 resetExecution 进入 Completed(避免 Paused + 空栈 断言崩溃);global 在未绑定 ProjectGlobalStore 的单脚本调试场景回退到参数槽(避免 F5/F6/F10 出现未定义);F2/F3 在当前文件首行就地重置(RunDebugReset),不回跳旧 IP,重置后可直接 F5/F6/F10;functionDeclAtLine 在首轮 sourceFilePath 场景回退路径匹配,保证“首轮/F2后”函数声明扫描一致;F6 可视策略:未执行语句行跳过,但结构行(else/case/default/})及空白/注释保留可见;switch 命中前允许看到 case 标签,break/continue/return 后直接落到下一可执行语句;for Step Over 迭代落循环体首行;结束态 RunSessionEnded(completed|stopped|error) — completed 保留 EOF 箭头,stopped 清箭头(Stop 路径不回写第1行箭头),error 保留 IP 须 Reset;Idle 打开 .ys 自动置首行箭头,切到 .yslib/非 .ys 自动清理箭头与调试路径
  • 项目树默认展开ProjectTreeWidget 启动/刷新后仅展开 active 项目,无 active 时全部折叠

R3 更新闭环与触发链路(已交付)

  • Apply 主流程LauncherService::applyUpdate() — manifest 缓存 → zip 定位/下载 → zipSha256 必填 → staging 解压 → ProjectValidator → 原子替换(保留 logs/)→ 失败回滚;QtConcurrent 后台 Apply,UI 不长时间阻塞
  • 安全基建FileService 安全解压(防 zip slip)、目录备份/替换;UpdateManifestVerifier::verifyFileSha256AppPaths::update*Path();HTTPS 下载 超时 abort,不使用不完整 manifest/zip
  • 组件更新(manifest)runtime / launcher / editor 段(setupUrl + setupSha256);Apply 后 非阻断 引导运行 NSIS 补丁包
  • 触发链路SubTaskWorker::onHardwareTrigger() + 队列 burst 不丢触发;TriggerMockService;Runtime --trigger-mock=camA 与 UI「Mock 硬件触发」
  • mini dumpMiniDumpWriter%LOCALAPPDATA%/CodePlanet/dumps/
  • NSIS 安装/补丁installer/nsis/*.nsi一键打包 installer/build_release_packages.ps1(清 staging → 复制 bin\ → windeployqt → makensis);或 scripts/build_nsis_packages.ps1;安装根目录 $INSTDIR + 注册表 App Paths CodePlanetr.exe
  • U 盘更新测试脚本:默认输出 dist/CodePlanetrUpdate/;可用 installer/run_r3_update_pipeline.ps1 串行执行 build/prepare/sign/verify,installer/copy_codeplanetr_update_to_drive.ps1 -DriveLetter G 复制到 U 盘;manifest 签名 canonical 必须与 Qt 字母序规则一致
  • Launcher 倒计时页:优先显示本次会话新增 launcher.log,无新增日志时显示 config/license.txt
  • 安装默认目录:NSIS 默认建议路径为 D:\CodePlanet(用户仍可在目录页改盘符)
  • Apply 项目路径归一化:优先定位当前安装目录 USER/projects,避免误用历史 C:\Program Files\CodePlanet 路径
  • 组件补丁引导策略:Apply 前弹出勾选窗口并先做可用性扫描;Runtime/Editor 可自动启动补丁安装,Launcher 因文件占用保留手动安装
  • 补丁安装覆盖策略:Runtime/Editor 补丁安装时 Qt DLL/插件若已存在则跳过覆盖,仅补充缺失文件,避免 Launcher 占用导致弹窗阻塞
  • 倒计时自动启动策略:倒计时到期后,若检测到已验证更新则进入更新页面,由用户手动选择“应用更新/跳过”;若无更新则直接启动 Runtime(未指定 yslib 时按失败流程提示)
  • 版本元数据约定:唯一维护入口为 resources/config/release_version.json;脚本仅自动更新 productVersion/shortVersion/buildlauncher/runtime/editor 保留手工值
  • 发包命名约定:全量包保留 CodeplanetrSetup-latest.exe,每次构建前自动归档旧包为 CodeplanetrSetup-{productVersion}.exe;组件补丁包文件名版本优先读取 runtimePackageVersion/launcherPackageVersion/editorPackageVersion(缺省回退对应组件版本前三段)
  • demo payload 版本约定prepare_r3_udisk_payload.ps1 默认读取 release_version.json.demoProjectVersion,用于 demo-{version}.zip 与 manifest projects.version
  • 构建清理约定dist/CodePlanet/bindist/CodePlanet/Update/* 每次构建均清理;仅 dist/CodePlanet/Download 保留全量包历史归档
  • shortVersion 约定:由 productVersion 前三段自动同步,手工改版本请改 productVersion
  • 回归scripts/run_r3_update_regression.ps1scripts/run_r3_regression.ps1(= R2 + update + NSIS smoke)
  • Mock 工具scripts/mock_hardware_trigger.ps1

R3 验签排障沉淀(必读)

  • zipSha256(项目 zip 文件哈希)与 canonical_sha256(manifest 规范化文本哈希)是不同对象,不能互相比较
  • 运行设备不依赖 OpenSSL;OpenSSL 仅用于开发机签名与本地验签脚本
  • 若出现“脚本验签通过但 Launcher 失败”,先对比 canonical_sha256:不一致通常是 canonical 规则或文件版本不一致
  • 签名脚本 canonical 必须与 Qt 字母序规则一致;脚本升级后旧 manifest 需要重新签名
  • plugins[].path 兼容两种相对路径:bin/plugins/...(相对安装根)和 plugins/...(相对 applicationDirPath

bin/dist/CodePlanet/bin/(勿维护两套)

目录 来源 用途
bin/ Qt Creator 编译(各 .proDESTDIR = $$ROOT/bin 日常开发运行、deploy_bin.ps1
dist/CodePlanet/bin/ deploy_staging.ps1bin/ 复制 + windeployqt NSIS 编译时打包素材;可整目录删除后重建

NSIS 不会在客户机读取 dist/makensis 在开发机把 staging 文件嵌入 exe。发版步骤见 docs/AST审计执行报告/R3-验收与操作手册.md §3。

Release 本机验收(R2 起推荐)

1. Qt Creator:Release Kit → 构建全部(覆盖 bin/*.exe) 2. 项目根目录:powershell -NoProfile -ExecutionPolicy Bypass -File scripts\deploy_bin.ps1 -Config Releasewindeployqt,须与 exe 同 Debug/Release) 3. 启动:powershell -File scripts\run_launcher_dev.ps1 -Config Releasebin\CodePlanetr.exe

改界面 tr() 文案时才需 update_i18n_ts.bat → 编辑 .tsgenerate_i18n.bat;普通 C++ 改动 不必单独「编译翻译」。

Runtime 分层:依赖 src/logic/src/core/src/services/ 与最小 Qt Widgets;不含 Ops 编辑器。Ops RuntimeWorker 不变(F5 调试)。

core 源文件链接约定(R2):凡目标编入 FunctionDispatcher.cpp,须同时编入 MainTaskTimerService.cppScriptAnalyzer 对 timer 的静态检查仅用头文件内联 isTimerFunction,Launcher 无需链接 timer 实现。

多脚本参数槽(R2):产线 Runtime 按 yslib scripts[] 为每个脚本分配 scriptId(从 1 递增)。RuntimeTaskContext::setScriptsAstRuntime::setScriptId 会调用 ensureSourceParameterSlots(id+1),避免 sourceParameterL.at(id) 越界。主任务循环脚本中 timer_create 仅应执行一次(用 static 守卫),每 tick 会重入 main()

头文件约定(R1):GUI 使用 ast::AnalyzeContext 时须 #include "ScriptAnalyzer.h"(勿仅含 AstCommon.h)。

Qt MOC 约定:含 Q_OBJECT 的类,.h 须列入 src/editor/editor.proHEADERS,否则链接报 LNK2019。

中间产物editor.pro / tests.proMOC_DIROBJECTS_DIR 使用 $$OUT_PWD,避免影子构建 Debug/Release 共用 moc 导致 LNK2038。改 .pro 后重新 qmake 并全量构建;旧版若曾在源码树 build/moc 留下产物,请删除后再编。

环境

  • Qt 5.15+ 或 Qt 6.x(Widgets、Sql、Concurrent 模块)
  • C++17 编译器(MSVC / MinGW)
  • 使用 Qt Creator 打开根目录 [CodePlanet.pro](../CodePlanet.pro)

构建

qmake CodePlanet.pro
# MSVC: nmake   /  MinGW: mingw32-make

MSVC + Qt 5.11 注意editor.pro 须显式 QMAKE_CXXFLAGS += /std:c++17(P5 使用 std::optional);改 .pro 后请在 Qt Creator 执行 重新运行 qmake 再编译。

Launcher 头文件约定:类内嵌套类型(如 CachedUpdateApplyResult)若作为 static 成员函数参数/返回值,须在首次使用之前完成定义(MSVC 否则报 C3646「未知重写说明符」);避免重复声明同一成员函数。

输出:bin/CodeEditor.exebin/CodePlanetr.exebin/CodeRuntime.exe,插件在 bin/plugins/BuiltinFunctions.dll

目录结构(禁止在旧路径新增代码)

src/editor       入口、MainWindow、Application(CodeEditor.exe)
src/runtime      CodeRuntime(产线任务执行 + 状态 UI)
src/launcher     CodePlanetr(启动守门)
src/gui          编辑器与 IDE 控件
src/logic        ControlLogiLib、RuntimeWorker 运行编排
src/core         运行时、类型、参数、图像、函数元数据
src/services     AppPaths、FileService、DatabaseService、PluginManager、DebugLogService
plugins/         Qt 动态库(IFunctionPlugin)
resources/       config/FunctionLib.ini、icons/、resources.qrc
examples/        示例 .ys 脚本
tests/           Qt Test 回归(CodePlanetTests)
scripts/         i18n 脚本、check_layer_includes.ps1、run_tests.ps1、run_all_checks.ps1

勿保留 已废弃的 CodePlanetr/ 嵌套副本、EG_File/、根目录 ICO/、根目录 FunctionLib.ini 等旧布局。

依赖规则

  • gui 可依赖 core/functionsservices
  • logic 依赖 core/runtime不得依赖 gui
  • core 不得依赖 guilogic
  • 插件仅通过 FunctionCallContext 访问运行时,不 include GUI 头文件

分层检查(P4)

编译期仍使用单 editor.pro 目标;分层约束由脚本强制执行:

powershell -NoProfile -ExecutionPolicy Bypass -File scripts/check_layer_includes.ps1
  • src/logic 不得 #include 任何 gui/ 头文件
  • src/core 不得 #include gui/logic/ 头文件
  • 违规时 exit 1 并打印文件路径;CI 或提交前建议运行

质量检查(P5)

本项目在 Windows 上使用 PowerShell + 批处理 跑分层检查与 Qt Test,无需手动配置 PATH。Agent 与开发者提交前建议执行。

一键检查(推荐)

项目根目录打开 PowerShell,执行:

cd E:\HuaweiMoveData\Users\MateBookXPro\Desktop\CodePlanetr
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\run_all_checks.ps1

成功标志:最后一行输出 All checks passed.,进程 exit code 为 0

脚本顺序:

1. scripts/check_layer_includes.ps1 — 分层 #include 违规扫描 2. scripts/run_tests.ps1 → 内部调用 scripts/build_tests.bat — 编译并运行 bin\CodePlanetTests.exe

本机工具链路径(已写入脚本默认值)

组件 路径
Qt 5.11.1(msvc2017_64) D:\Qt\Qt5.11.1\5.11.1\msvc2017_64
qmake 上述目录下 bin\qmake.exe
Visual Studio 2017 D:\Visual Studio\2017\Community
vcvars ...\VC\Auxiliary\Build\vcvars64.bat

若 Qt 安装位置变更,可临时覆盖:

$env:QTDIR = "D:\Qt\Qt5.11.1\5.11.1\msvc2017_64"
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\run_all_checks.ps1

或编辑 scripts/build_tests.bat / scripts/run_tests.ps1 中的候选路径。

分项运行

目的 命令
仅分层检查 powershell -NoProfile -ExecutionPolicy Bypass -File scripts\check_layer_includes.ps1
仅单元测试 powershell -NoProfile -ExecutionPolicy Bypass -File scripts\run_tests.ps1
仅测试(不经过 PowerShell 包装) 双击或 cmd /c scripts\build_tests.bat

测试产物:bin\CodePlanetTests.exebin\testresults.xml(XML 报告)。

自动化未覆盖项(需 GUI 手动)

  • examples\ast_debug.ys:Ctrl+B → F5 / F6 / F10
  • examples\expr_p1_test.ys:F5
  • 参数面板运行中修改 / 删除变量

详见 docs/AST审计执行报告/P5-阶段交付报告.md §6。

调试日志(P4 + P5)

  • 统一出口:ControlLogiLib::publishDebugMessageDebugLogService::log(lineNo, msg) + SendDebugMessage 信号 → UI
  • 插件:FunctionCallContext::sendDebugMessageFunctionDispatcher::setDebugMessageSink(P5)
  • 全局 SendDebugMessage 回调(parameterparser.h)已 deprecated,仅经 Init_DebugMessage 注册后转发
  • RuntimeWorker::debugMessage 在 AST 解析失败时从 (at line:col) 提取行号写入 DB

最近文件(P4)

  • DatabaseService::addRecentFile / recentFiles / removeRecentFile
  • UI:文件菜单 →「最近打开」,读取 SQLite recent_files

命名与 API 约定

约定 说明
类名 PascalCase,与文件名一致
信号槽 动词开头,如 RunButtonClickSendDebugMessage
路径 禁止硬编码绝对路径;使用 AppPaths::
读写文件 FileService::readTextFile / writeTextFile(UTF-8)
脚本 扩展名 .ys、库清单 .yslib

P4 已清理拼写错误 API(src/ 无旧名残留):

旧名 处置 / 当前 API
HeightLightError 移除 → CodeEditor::applyBuildDiagnostics(BuildResult) 绘制波浪线
SendBulidMessage 移除 → CodeEditorWidget::handleBuildResult(BuildResult) 填充问题面板
ParaUpdata 重命名 → ControlLogiLib::updateParameters()

Build 信号链路:CodeEditor::buildFinished(ast::BuildResult)CodeEditorWidget::handleBuildResult(connect 在 codeeditorwidget2.cpp)。

FunctionCatalog(P2)

  • FunctionCatalogFunctionLib.ini 唯一解析入口(FileService 读文件)
  • 控制流/高亮/补全关键字在 INI 的 [ControlFlow][Highlight] 等段配置,禁止在编辑器源码重复硬编码
  • Application 启动加载 Catalog 后校验插件函数名

编辑器模块(P3)

src/gui/editor/ 已拆分,codeeditor.cpp 仅保留核心编辑逻辑(≤800 行):

文件 职责
codeeditor.cpp 构造、搜索高亮、键盘/鼠标核心、调试箭头等
buildprogram.cpp Ctrl+B 入口,调用 ScriptAnalyzer 并绘制诊断波浪线
ScriptAnalyzer.cpp 静态检查引擎(词法/语法/语义,见下表)
LineNumberArea.cpp 行号 gutter 绘制与断点/折叠点击
EditorFoldManager.cpp 折叠区域解析与 toggle
CppSyntaxHighlighter.cpp 语法高亮(与 YsHighlightScanner 并存)
CustomScrollBar.cpp 搜索匹配滚动条标记
CodeEditorCompletion.cpp 函数库补全
EditorBracketHighlight.cpp 括号/参数高亮
CodeEditorIndent.cpp 自动缩进

Ctrl+B 静态检查(ScriptAnalyzer)

阶段 代码前缀 说明
预处理 YS001 字符串引号未成对
词法 YS1xx Lexer 错误
语法 YS2xx Parser 错误
语义 YS301 作用域内重复变量(警告)
语义 YS302 重复 function 定义(错误)
语义 YS303 未定义函数/指令(错误)
语义 YS304/305 break/continue 位置非法
语义 YS306 函数参数名重复
语义 YS307 库函数参数个数不匹配(警告)

运行策略(与 VS Code/MSVC 一致):错误阻止 F5/F6;警告不阻止。F5/F6 预检为静默模式,仅在有错误时切到「问题」面板;Ctrl+B 始终打开问题面板。

Debug 日志:ReceiverDebugMessage 直接 m_debugEdit->append 100ms CycTimer

新增脚本函数

1. 编辑 resources/config/FunctionLib.ini(CSV 函数行 + 可选 [Plugin]

  • 插件函数也须写 CSV 行(含 para_count),否则 Ctrl+B 的 YS307 无法校验参数个数

2. 在插件中实现 IFunctionPlugin::execute(或扩展 BuiltinFunctions) 3. supportedFunctions() 注册函数名(匹配时不区分大小写) 4. 编译插件,部署到 bin/plugins/ 5. 用 examples/ 脚本验证

Git

  • 不提交 *.pro.userbuild/bin/
  • 提交说明写清「为什么」

编码

  • 源码与脚本默认 UTF-8
  • 旧 GBK 文件由 FileService 自动回退解码
  • MSVC:editor.pro 启用 /utf-8;勿使用 #pragma execution_character_set;固定中文用 QString::fromUtf8(u8"...")

界面国际化

  • Application::setLocale + tr() + 各控件 retranslateUi()
  • 维护流程见 [国际化维护说明.md](国际化维护说明.md)
  • 脚本:scripts/update_i18n_ts.batscripts/generate_i18n.bat

维护 .cursordocs

修改架构或上述约定时,请同时更新:

  • .cursor/开发指南.md.cursor/rules/*.mdc
  • docs/ 下对应文档

相关文档

  • [架构说明.md](架构说明.md)
  • [插件开发指南.md](插件开发指南.md)
  • [国际化维护说明.md](国际化维护说明.md)
  • [分析报告/项目分析报告.md](分析报告/项目分析报告.md)
  • [维护文件/AST逻辑架构.md](维护文件/AST逻辑架构.md)
  • [.cursor/README.md](../.cursor/README.md)

帮助阅读建议

  • 左侧目录可快速切换文档,右侧区域支持长文滚动阅读。
  • 遇到复杂流程,建议先阅读“项目目标与架构终点”再看部署规范。
  • 每份文档都保留原文入口,便于下载归档或离线传阅。