From 103b961e6fa030bdc113b37d2c9b5af83ed44e3f Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:50:48 +0800 Subject: [PATCH] =?UTF-8?q?docs(source-generators):=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=99=A8=E4=B8=93=E9=A2=98=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E5=B9=B6=E6=9B=B4=E6=96=B0=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Schema 配置生成器专题页,补充输入契约、生成物与诊断边界 - 更新 source-generators、API 参考与 CQRS 文档,说明共享支撑层阅读路线与 fallback 分层 - 更新 documentation-full-coverage-governance 的 tracking 和 trace,记录批次指标与验证结果 --- ...ation-full-coverage-governance-tracking.md | 28 ++- ...entation-full-coverage-governance-trace.md | 33 +++ docs/.vitepress/config.mts | 1 + docs/zh-CN/api-reference/index.md | 20 +- docs/zh-CN/core/cqrs.md | 5 + .../cqrs-handler-registry-generator.md | 35 +++ docs/zh-CN/source-generators/index.md | 15 +- .../schema-config-generator.md | 200 ++++++++++++++++++ 8 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 docs/zh-CN/source-generators/schema-config-generator.md diff --git a/ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md b/ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md index 27deef8a..60f7c878 100644 --- a/ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md +++ b/ai-plan/public/documentation-full-coverage-governance/todos/documentation-full-coverage-governance-tracking.md @@ -12,10 +12,14 @@ ## 当前恢复点 -- 恢复点编号:`DOCUMENTATION-FULL-COVERAGE-GOV-RP-050` +- 恢复点编号:`DOCUMENTATION-FULL-COVERAGE-GOV-RP-051` - 当前阶段:`Phase 5 - Governance Maintenance` - 当前焦点: - - 按 `$gframework-batch-boot 50` 继续推进 `documentation-full-coverage-governance`,沿用 `origin/main` 作为 stop-condition 基线,收口 `Game` / `Godot` 细页与少量 README 中残留的 reader-facing 措辞与标签问题 + - 按 `$gframework-batch-boot 50` 继续推进 `documentation-full-coverage-governance`,沿用 `origin/main` 作为 stop-condition 基线,在保持 reader-facing 口吻治理的同时,继续补 `source-generators` / `CQRS` 的公开专题覆盖率 +- `2026-04-30` 本轮恢复时确认当前 `HEAD` 与 `origin/main` 同步,committed diff 为 `0` files / `0` lines;因此本批次不再只做措辞收口,而是允许补新的公开专题页和入口链路 +- `2026-04-30` 本轮接受 2 个 explorer 的只读结论:其一,`GFramework.SourceGenerators.Common` 更适合作为 landing / API 入口内的共享排障层,而不是新的独立 public page;其二,`Cqrs.SourceGenerators` 当前主要缺口不是“没有入口”,而是现有专题页与 `core/cqrs.md` 对生成策略层级、fallback 精度和 `GF_Cqrs_001` 的解释不够 reader-facing +- `2026-04-30` 本批次已新增 `docs/zh-CN/source-generators/schema-config-generator.md`,并同步更新 `docs/zh-CN/source-generators/index.md`、`docs/zh-CN/api-reference/index.md`、`docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`、`docs/zh-CN/core/cqrs.md` 与 `docs/.vitepress/config.mts`,把 `Game.SourceGenerators` 的 schema 生成链路和 `Cqrs.SourceGenerators` 的定向 fallback 语义收敛成站内可见入口 +- 当前工作树相对 `origin/main` 已达到 `39` files / `2555` lines;仍低于 `50` 文件 stop condition,但后续若继续扩批,应优先提交本轮覆盖扩展后再开新批次 - `2026-04-29` 重新进入时确认当前分支仍为 `docs/sdk-update-documentation`,但 upstream `origin/docs/sdk-update-documentation` 已不存在;因此本轮不再把旧 PR review 线程作为默认恢复入口,而是以本地 diff vs `origin/main` 为主 - `2026-04-29` 上一批已完成 11 个低风险文档文件的收口:去掉 `ai-libs`、`旧文档`、`优先看` / `先看` / `转到` 这类内部或指令式措辞,并把 README 中暴露原始路径的链接标签改成 reader-facing 标题 - `2026-04-29` 本批次继续接受 2 个 explorer 的只读结论:一个负责 `game/data.md`、`game/storage.md`、`godot/ui.md` 的热点排序,一个负责 README reader-facing 标签巡检;主线程只接受低风险措辞问题,不扩展到结构重写 @@ -26,6 +30,9 @@ ## 当前状态摘要 - `Core`、`Ecs.Arch`、`Cqrs`、`Game`、`Godot` 五个模块族当前都已有 README / landing / topic / API 参考层级的已验证入口。 +- `2026-04-30` source-generators 栏目当前已补出新的 `Schema 配置生成器` 专题页,并通过 landing、API 入口和侧栏把 `Game.SourceGenerators` 从“只在 `config-system.md` 侧面提到”提升到独立 reader-facing 入口。 +- `2026-04-30` `docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` 与 `docs/zh-CN/core/cqrs.md` 当前已明确“有 fallback != 退回整程序集盲扫”,并补充 direct registration、实现类型定向反射、精确 service type lookup 与程序集级 fallback 元数据之间的分层关系。 +- `2026-04-30` `docs/zh-CN/api-reference/index.md` 与 `source-generators/index.md` 当前把 `SourceGenerators.Common`、`*.SourceGenerators.Abstractions` 收敛为共享 diagnostics / attribute / 冲突规则的阅读入口,而不是新的安装包或维护者专题页。 - `2026-04-29` 新一轮 batch boot 第 2 批次已进一步收口 `docs/zh-CN/game/data.md`、`game/storage.md`、`godot/ui.md` 与 `GFramework.Cqrs.Abstractions/README.md`、`GFramework.SourceGenerators.Common/README.md`:移除 “仓库和测试确认”“真实消费者 wiring”“CoreGrid 当前的做法”“优先看” 这类内部或生硬口吻,并把 CQRS 抽象层 README 的源文件列表改成契约类型族说明。 - `2026-04-29` 新一轮 batch boot 已收口 `docs/zh-CN/godot/storage.md`、`godot/setting.md`、`godot/signal.md`、`godot/logging.md`、`godot/index.md`、`game/scene.md`、`core/index.md`、`game/config-system.md`、`ecs/arch.md` 与 `GFramework.Godot/README.md`、`tools/gframework-config-tool/README.md` 的 reader-facing 文案:移除 `ai-libs`、旧文档对比、命令式跳转和原始路径标签。 - `2026-04-29` 当前分支的 upstream `origin/docs/sdk-update-documentation` 已 gone;后续若继续批处理,应继续以 `origin/main` 作为 branch-size stop condition 的 authoritative baseline,而不是默认恢复旧 PR review 状态。 @@ -70,6 +77,7 @@ - `dotnet build GFramework.csproj -c Release` 当前仍会输出仓库既有 analyzer warnings(如 `MA0158`、`MA0051`、`MA0004`);本轮仅修改文档与 package metadata,不扩展到 warning 清理。 - 当前分支 upstream 已 gone;在重新建立 remote branch 或新的 PR 之前,不适合再把旧 PR `#299` 的 review 状态当作默认恢复信号。 - 当前 batch boot 已从 `origin/main` 零 diff 状态重新起步;本轮仍是低风险措辞收口,但下一轮若继续深入 README 子系统地图或大段采用路径重写,review 面会明显扩大。 +- 当前工作树在 coverage 扩展后已接近 `$gframework-batch-boot 50` 的中后段窗口;如果继续新增 source-generator 或 README 专题,建议先提交本轮改动并重新计算 committed diff,再决定是否继续扩批。 - `GFramework.Cqrs`、`GFramework.Cqrs.SourceGenerators`、`GFramework.Game.SourceGenerators`、`GFramework.Ecs.Arch` 等 README 仍有若干源文件列表式“子系统地图”段落;这些已经接近结构级改写,不适合作为本轮剩余低风险批次继续机械推进。 ## 归档指针 @@ -91,6 +99,18 @@ ## 最新验证 +- `2026-04-30` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/schema-config-generator.md` + - 结果:通过;新增 `Schema 配置生成器` 专题页的 frontmatter、链接与代码块校验通过。 +- `2026-04-30` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/index.md` + - 结果:通过;source-generators landing 在补 `Schema 配置生成器` 与共享支撑层阅读路线后校验通过。 +- `2026-04-30` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` + - 结果:通过;`Cqrs` generator 专题页新增策略层级与 fallback 精度说明后校验通过。 +- `2026-04-30` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/core/cqrs.md` + - 结果:通过;`CQRS` 运行时页补充 generated registry 与 fallback 协作说明后校验通过。 +- `2026-04-30` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/api-reference/index.md` + - 结果:通过;API 入口页补充 `Game.SourceGenerators` 与共享 source-generator 支撑层阅读路线后校验通过。 +- `2026-04-30` `bun run build`(工作目录:`docs/`) + - 结果:通过;新增 source-generators 专题页与侧栏入口后站点仍可构建,仅保留既有大 chunk warning。 - `2026-04-29` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/game/data.md` - 结果:通过;`game/data.md` 的 frontmatter、链接与代码块校验通过。 - `2026-04-29` `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/game/storage.md` @@ -132,7 +152,7 @@ ## 下一步 -1. 提交本轮第 2 批低风险 reader-facing 文案批次,并在提交后重新计算 branch diff vs `origin/main`,确认仍明显低于 `50` 文件 stop condition。 -2. 若继续下一批,优先挑选仍可“局部改句子”的页面或 README 标签问题;`Cqrs`、`Game.SourceGenerators`、`Ecs.Arch` 这类源文件列表式 README 应视作结构级专题,必要时单独开一轮更明确的写作目标。 +1. 提交本轮 source-generators / CQRS coverage 扩展批次,并在提交后重新计算 committed branch diff vs `origin/main`,确认是否仍适合继续在同一 `$gframework-batch-boot 50` 窗口内推进。 +2. 若继续下一批,优先挑选“已有 package README、但站内专题仍不足”的模块入口,例如 `README` 与现有 docs 之间的采用路径补链;避免把 `SourceGenerators.Common` 之类共享支撑层继续扩写成维护者导向的独立专题。 3. 只有在重新建立 remote branch 或新的 PR 之后,再恢复 `$gframework-pr-review` 作为默认恢复入口;在此之前以本地 diff 与验证结果为准。 4. 若后续分支继续调整 `Game` persistence runtime、README 或公共 API,优先复核 `docs/zh-CN/game/data.md`、`storage.md`、`serialization.md`、`setting.md` 与 landing page 是否仍保持同一套职责边界。 diff --git a/ai-plan/public/documentation-full-coverage-governance/traces/documentation-full-coverage-governance-trace.md b/ai-plan/public/documentation-full-coverage-governance/traces/documentation-full-coverage-governance-trace.md index b7de3b1c..c3b129a9 100644 --- a/ai-plan/public/documentation-full-coverage-governance/traces/documentation-full-coverage-governance-trace.md +++ b/ai-plan/public/documentation-full-coverage-governance/traces/documentation-full-coverage-governance-trace.md @@ -2,6 +2,39 @@ ## 2026-04-29 +### 当前恢复点:RP-051 + +- 本轮按 `$gframework-batch-boot 50` 恢复后,先确认 `HEAD` 与 `origin/main` `79f9cb37`(`2026-04-29 22:59:12 +08:00`)同步,committed diff 为 `0` files / `0` lines,因此允许把批次目标从“低风险句子收口”提升为“补新的 docs coverage 入口”。 +- 主线程保留实现与验证,同时接受了 2 个 explorer 的只读结论:一条用于判断 `SourceGenerators.Common` 是否值得升成独立 public page,一条用于判断 `Cqrs.SourceGenerators` 的真实公开缺口。accepted 结论是:共享 source-generator 支撑层更适合补 landing / API 入口,而 `Cqrs.SourceGenerators` 应增强现有专题页对策略层级与 fallback 精度的解释。 +- 一个 worker 曾被短暂分配去草拟独立 `shared-support-modules` 页面,但在 explorer 结论返回后被中断;最终无文件写入,也没有并行实现遗留。 +- 实际落地的 coverage 扩展集中在 6 个文件:新增 `docs/zh-CN/source-generators/schema-config-generator.md`,并更新 `docs/zh-CN/source-generators/index.md`、`docs/zh-CN/api-reference/index.md`、`docs/zh-CN/source-generators/cqrs-handler-registry-generator.md`、`docs/zh-CN/core/cqrs.md` 与 `docs/.vitepress/config.mts`。 +- docs 页面与恢复文档更新完成后,工作树相对 `origin/main` 已到 `39` files / `2555` lines;仍低于 `50` 文件 stop condition,但本轮已不再适合继续新开第三类 coverage 切片。 + +### 当前决策(RP-051) + +- `Game.SourceGenerators` 当前公开缺口足够明确,因此直接补一张新的 reader-facing 专题页,专门解释 schema 输入契约、生成物形态、聚合注册入口和 `ConfigSchemaDiagnostics` 边界。 +- `SourceGenerators.Common`、`Core.SourceGenerators.Abstractions`、`Godot.SourceGenerators.Abstractions` 不提升为新的独立 public docs 页面,只在现有 landing / API 入口里补共享 diagnostics、attribute 契约与冲突规则的阅读路线。 +- `Cqrs.SourceGenerators` 不再新增第二张专题页,而是在现有 `cqrs-handler-registry-generator.md` 与 `core/cqrs.md` 内明确“有 fallback != 整程序集盲扫”、direct registration / reflected implementation / precise service type lookup / assembly fallback 的层级关系,以及 `GF_Cqrs_001` 的 reader-facing 判断顺序。 + +### 当前验证(RP-051) + +- 页面校验: + - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/schema-config-generator.md` + - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/index.md` + - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/cqrs-handler-registry-generator.md` + - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/core/cqrs.md` + - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/api-reference/index.md` + - 结果:通过;本轮新增专题页与 4 个入口页 / 专题页校验全部通过。 +- 站点构建: + - `bun run build`(工作目录:`docs/`) + - 结果:通过;新增 `Schema 配置生成器` 侧栏入口后站点仍可构建,仅保留既有大 chunk warning。 + +### 下一步(RP-051) + +1. 提交本轮 source-generators / CQRS coverage 扩展批次,并把 committed diff vs `origin/main` 重新写回 active tracking。 +2. 若继续同一主题,优先挑选“已有用户面 package,但站内专题仍需补链”的模块,而不是继续给共享支撑层单开页面。 +3. 在 remote branch / PR 恢复之前,继续把 `origin/main` + branch-size 指标当作唯一 batch stop condition。 + ### 当前恢复点:RP-050 - 本轮继续按 `$gframework-batch-boot 50` 推进,并沿用 `origin/main` `4557dde6`(`2026-04-29 11:14:56 +08:00`)作为唯一 branch-size baseline。 diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index bba97579..18ec3851 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -248,6 +248,7 @@ export default defineConfig({ text: '源码生成器', items: [ { text: '概览', link: '/zh-CN/source-generators/' }, + { text: 'Schema 配置生成器', link: '/zh-CN/source-generators/schema-config-generator' }, { text: '日志生成器', link: '/zh-CN/source-generators/logging-generator' }, { text: '枚举扩展生成器', link: '/zh-CN/source-generators/enum-generator' }, { text: 'ContextAware 生成器', link: '/zh-CN/source-generators/context-aware-generator' }, diff --git a/docs/zh-CN/api-reference/index.md b/docs/zh-CN/api-reference/index.md index 5573089e..278c8f99 100644 --- a/docs/zh-CN/api-reference/index.md +++ b/docs/zh-CN/api-reference/index.md @@ -31,8 +31,8 @@ description: GFramework 的 API 阅读入口,按模块映射 README、专题 | 模块族 | 先看什么 | 继续深入 | XML 文档关注点 | | --- | --- | --- | --- | | `Core` / `Core.Abstractions` | [Core 模块](../core/index.md) | [Core 抽象层说明](../abstractions/core-abstractions.md)、[快速开始](../getting-started/quick-start.md) | 架构入口、生命周期、命令 / 查询 / 事件 / 状态 / 资源 / 日志 / 配置 / 并发契约 | -| `Cqrs` / `Cqrs.Abstractions` / `Cqrs.SourceGenerators` | [CQRS 运行时](../core/cqrs.md) | [CQRS Handler Registry 生成器](../source-generators/cqrs-handler-registry-generator.md)、[协程系统](../core/coroutine.md) | request / notification / handler / pipeline / generated registry / targeted fallback contract | -| `Game` / `Game.Abstractions` / `Game.SourceGenerators` | [Game 模块总览](../game/index.md) | [Game 抽象层说明](../abstractions/game-abstractions.md)、[配置系统](../game/config-system.md) | 配置、数据、设置、场景、UI、存储、序列化契约;其中 AI-First 配置工作流的正式支持边界以 Runtime + Generator 共享 schema 子集为准 | +| `Cqrs` / `Cqrs.Abstractions` / `Cqrs.SourceGenerators` | [CQRS 运行时](../core/cqrs.md) | [CQRS Handler Registry 生成器](../source-generators/cqrs-handler-registry-generator.md)、[协程系统](../core/coroutine.md) | request / notification / handler / pipeline / generated registry / targeted fallback contract,以及生成注册器与定向补扫的协作边界 | +| `Game` / `Game.Abstractions` / `Game.SourceGenerators` | [Game 模块总览](../game/index.md) | [Game 抽象层说明](../abstractions/game-abstractions.md)、[配置系统](../game/config-system.md)、[Schema 配置生成器](../source-generators/schema-config-generator.md) | 配置、数据、设置、场景、UI、存储、序列化契约,以及 schema 到生成代码的公开入口 | | `Godot` / `Godot.SourceGenerators` | [Godot 模块总览](../godot/index.md) | [Godot 项目生成器](../source-generators/godot-project-generator.md)、[GetNode 生成器](../source-generators/get-node-generator.md)、[BindNodeSignal 生成器](../source-generators/bind-node-signal-generator.md) | 节点扩展、场景 / UI 适配、配置 / 存储 / 设置接线、Godot 生成器入口 | | `Ecs.Arch` / `Ecs.Arch.Abstractions` | [ECS 模块总览](../ecs/index.md) | [Arch ECS 集成](../ecs/arch.md)、[Ecs.Arch 抽象层说明](../abstractions/ecs-arch-abstractions.md) | ECS 模块契约、系统适配、配置对象和运行时装配边界 | @@ -78,6 +78,22 @@ description: GFramework 的 API 阅读入口,按模块映射 README、专题 - `GFramework.SourceGenerators.Common` - 主要提供共享生成器基类、通用 diagnostics,以及生成方法冲突等跨模块约束。 +如果你要沿着 XML 文档和源码继续读,优先从下面这几类入口开始: + +- 共享 diagnostics + - `CommonDiagnostics` +- 共享生成流程 + - `AttributeClassGeneratorBase` + - `AttributeEnumGeneratorBase` +- 共享冲突规则 + - `GeneratedMethodConflictExtensions` + +这组入口更适合回答三类问题: + +- 为什么多个生成器都会要求宿主类型满足 `partial` +- 为什么不同专题页会出现同一套生成方法名冲突诊断 +- 为什么多个生成器对候选筛选、属性解析和生成阶段采用相近流程 + ## 使用方式 把本页当成“API 阅读导航”而不是“签名快照”: diff --git a/docs/zh-CN/core/cqrs.md b/docs/zh-CN/core/cqrs.md index c705bfd3..2a62250d 100644 --- a/docs/zh-CN/core/cqrs.md +++ b/docs/zh-CN/core/cqrs.md @@ -184,6 +184,11 @@ protected override void OnInitialize() 两者的共同点都是“优先消费 generated invoker 元数据,未命中时保留既有反射绑定作为兜底”,而不是要求业务侧切换到另一套 runtime 入口。 +对接入方来说,更关键的 reader-facing 语义是:安装 `Cqrs.SourceGenerators` 后,不要求“所有 handler 都能被生成代码直接引用”才有收益。 +即使仍有 fallback,runtime 也会先消费 generated registry,再只对剩余 handler 做定向补扫;只有旧版 marker 语义或空 fallback 元数据才会退回整程序集扫描。 +`Type` fallback、按名称恢复的 fallback,以及 mixed fallback 只影响补扫精度,不改变 +`RegisterCqrsHandlersFromAssembly(...)` 或 `RegisterCqrsHandlersFromAssemblies(...)` 的接法。 + `Cqrs.SourceGenerators` 的专题入口见[CQRS Handler Registry 生成器](../source-generators/cqrs-handler-registry-generator.md)。 ## Pipeline Behavior diff --git a/docs/zh-CN/source-generators/cqrs-handler-registry-generator.md b/docs/zh-CN/source-generators/cqrs-handler-registry-generator.md index 94c38765..3b973d5b 100644 --- a/docs/zh-CN/source-generators/cqrs-handler-registry-generator.md +++ b/docs/zh-CN/source-generators/cqrs-handler-registry-generator.md @@ -124,11 +124,46 @@ RegisterCqrsHandlersFromAssemblies( - 其余场景统一回退到字符串元数据,避免 mixed 场景漏注册 - 只有在 runtime 提供 `CqrsReflectionFallbackAttribute` 合同时,才允许发射依赖 fallback 的结果 +## 生成策略层级 + +把这个生成器理解成“静态注册 or 整程序集扫描”的二选一,会低估它的收益。当前策略实际上分成四层: + +1. 直接静态注册 + - handler 接口和实现类型都能被生成代码安全引用 +2. 实现类型定向反射查找 + - handler 接口还能精确表达,但实现类型只能在运行时按具体类型名恢复 +3. service type 精确运行时查找 + - handler 接口本身也需要运行时构造,但仍能把查找范围收窄到具体 service type +4. 程序集级 fallback 元数据 + - 只有前面几层都无法覆盖的剩余 handler,才交给 `CqrsReflectionFallbackAttribute` + +这意味着安装生成器后,并不要求“所有 handler 都可直接引用”才有收益。很多只能部分静态表达的项目,仍然可以把大部分注册路径前移到编译期,再对少数复杂类型做定向补扫。 + +## 哪些场景通常不会直接退回整程序集扫描 + +下列类型形态经常仍然能保留精细化注册,而不是立刻退回整程序集盲扫: + +| 场景 | 常见结果 | +| --- | --- | +| 私有嵌套 handler,但对外 handler 接口仍可直接引用 | 生成器改为按实现类型定向反射查找 | +| 响应或参数里包含需要运行时恢复的隐藏类型 | 生成器改为精确 service type runtime lookup | +| mixed 场景里同时存在可直接引用和仅能按名称恢复的 fallback handlers | 生成器拆分 `Type` 元数据和字符串元数据,减少后续字符串回查 | +| 响应类型写成 `dynamic` | 生成器会按 `System.Object` 归一化,而不是发射非法的 `typeof(dynamic)` | + +相反,pointer、function-pointer 这类无法安全重建的类型形态,不属于这里承诺的精确生成边界。 + 如果当前编译环境缺少这个 fallback 合同,而某些 handler 又必须依赖它,生成器会报: - `GF_Cqrs_001` 这条诊断的含义不是“某个 handler 写错了”,而是“当前 runtime 合同不足以安全承载这轮生成结果”。 +遇到它时,优先按这个顺序判断: + +1. 当前消费端是否已经引用支持 `CqrsReflectionFallbackAttribute` 的 `GFramework.Cqrs` runtime +2. 当前项目里是否存在只能部分静态表达的 handler 类型 +3. 如果确实不想引入 fallback 合同,是否需要把这类 handler 改成更容易被生成器直接引用的公开形态 + +`CqrsReflectionFallbackAttribute` 出现也不等于“运行时一定回到整程序集扫描”。只有 fallback 元数据为空、或旧版只保留 marker 语义时,runtime 才会退回整程序集补扫;当元数据里已经带了具体 `Type` 或类型名时,runtime 会优先按这些剩余 handler 做定向补扫。 ## 源码与 API 阅读入口 diff --git a/docs/zh-CN/source-generators/index.md b/docs/zh-CN/source-generators/index.md index e4f1981a..55ac039d 100644 --- a/docs/zh-CN/source-generators/index.md +++ b/docs/zh-CN/source-generators/index.md @@ -25,7 +25,7 @@ GFramework 当前发布的生成器包是: | 使用场景 | 安装包 | 继续阅读 | | --- | --- | --- | | 减少日志、上下文注入、模块自动注册等 Core 侧样板代码 | `GeWuYou.GFramework.Core.SourceGenerators` | [Core 模块](../core/index.md)、[日志生成器](./logging-generator.md)、[ContextAware 生成器](./context-aware-generator.md) | -| 把 `schemas/**/*.schema.json` 生成成配置类型和表包装 | `GeWuYou.GFramework.Game.SourceGenerators` | [配置系统](../game/config-system.md)、[VS Code 配置工具](../game/config-tool.md) | +| 把 `schemas/**/*.schema.json` 生成成配置类型和表包装 | `GeWuYou.GFramework.Game.SourceGenerators` | [Schema 配置生成器](./schema-config-generator.md)、[配置系统](../game/config-system.md)、[VS Code 配置工具](../game/config-tool.md) | | 让 CQRS handler registry 在编译期生成,缩小运行时反射扫描范围 | `GeWuYou.GFramework.Cqrs.SourceGenerators` | [CQRS 运行时](../core/cqrs.md)、[CQRS Handler Registry 生成器](./cqrs-handler-registry-generator.md) | | 在 Godot 项目里生成 AutoLoad / Input Action 入口、节点 / 信号样板,或补齐 Scene/UI 包装与导出集合注册辅助 | `GeWuYou.GFramework.Godot.SourceGenerators` | [Godot 模块总览](../godot/index.md)、[Godot 项目生成器](./godot-project-generator.md)、[GetNode 生成器](./get-node-generator.md) | @@ -94,6 +94,15 @@ GFramework 当前发布的生成器包是: - 再根据 attribute 或 diagnostics 回到对应专题页 - 只有在排查生成失败原因时,才继续下钻到这些共享支撑目录 +如果你更关心“多个生成器为什么会给出一致的 `partial` 要求、方法名冲突错误或 trace 诊断”,可以把这三类目录当成共享排障层来理解: + +- `*.SourceGenerators.Abstractions` + - 先看公开 attribute 能写什么,再回到对应专题页确认生成语义 +- `GFramework.SourceGenerators.Common` + - 先看共享 diagnostics,再看公共生成基类和冲突规则 + +这层仍然不是新的安装入口。只有在排查生成失败、对比多个生成器的共同约束,或准备扩展生成器时,才值得继续下钻。 + ## 阅读路线 ### Core 侧通用生成器 @@ -107,6 +116,8 @@ GFramework 当前发布的生成器包是: ### Game / CQRS 相关生成器 +- schema 到配置类型 / 表包装 / 聚合注册的生成路径: + - [Schema 配置生成器](./schema-config-generator.md) - 配置 schema 生成与运行时接法: - [配置系统](../game/config-system.md) - 读者若需要确认共享 schema 子集、关闭对象边界或复杂组合关键字的限制,应以该页为准,而不是只从本页推断支持范围 @@ -138,6 +149,8 @@ GFramework 当前发布的生成器包是: - 安装 `Game` + `Game.SourceGenerators` - 需要 CQRS 生成注册表: - 安装 `Cqrs` + `Cqrs.SourceGenerators` +- 需要排查跨生成器共享的 diagnostics 或 attribute 契约: + - 保持原有 `*.SourceGenerators` 包入口不变,再回到本页的共享支撑模块说明 ## 对应模块入口 diff --git a/docs/zh-CN/source-generators/schema-config-generator.md b/docs/zh-CN/source-generators/schema-config-generator.md new file mode 100644 index 00000000..0d78eb45 --- /dev/null +++ b/docs/zh-CN/source-generators/schema-config-generator.md @@ -0,0 +1,200 @@ +--- +title: Schema 配置生成器 +description: 说明 GFramework.Game.SourceGenerators 如何从 schema 生成配置类型、表包装和聚合注册入口。 +--- + +# Schema 配置生成器 + +`GFramework.Game.SourceGenerators` 会把消费者项目里的 `schemas/**/*.schema.json` 读入编译期管线,并生成: + +- 强类型配置类型 +- 对应的表包装类型 +- 单表绑定辅助代码 +- 聚合注册目录与 `RegisterAllGeneratedConfigTables(...)` 扩展入口 + +如果你当前目标是“先把配置系统接进项目”,先看 [游戏内容配置系统](../game/config-system.md)。这页更适合在你已经决定使用 +`Game.SourceGenerators` 之后,继续确认 schema 输入契约、生成结果和常见诊断边界。 + +## 它解决什么问题 + +相比只写 `YAML` 和运行时加载代码,这个生成器把三件事前移到了编译期: + +- 把 schema 转成 `Config` 类型,让业务代码直接拿到强类型字段和 XML 文档 +- 为运行时表生成包装层,让 `Get`、`TryGet`、按字段查找等入口保持稳定 +- 汇总当前项目中所有 schema 的注册信息,避免 schema 数量增长后继续手写逐表注册 + +这也是 `GFramework.Game` 配置运行时、VS Code 配置工具和 schema 约束能够共享同一份结构定义的基础。 + +## 最小接入路径 + +NuGet 安装保持运行时包与生成器包版本一致,并把生成器声明为编译期依赖: + +```xml + + + + +``` + +默认情况下,包内 `targets` 会自动把 `schemas/**/*.schema.json` 纳入 `AdditionalFiles`。如果你的 schema 目录不是 +`schemas/`,可以在项目文件里覆盖: + +```xml + + GameSchemas + +``` + +## 输入约定 + +### schema 根对象 + +当前生成器要求每个 schema 都满足这些基本约束: + +- 顶层 `type` 必须是 `object` +- 必须声明必填 `id` 字段 +- `id` 目前只支持 `integer` 和 `string` +- schema 文件名与属性名都必须能稳定映射到合法的 C# 标识符 + +最小示例: + +```json +{ + "title": "Monster Config", + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } +} +``` + +### 路径与索引元数据 + +除了标准 JSON Schema 字段,当前还支持几个会直接影响生成结果的扩展元数据: + +- `x-gframework-config-path` + - 覆盖默认配置目录;值必须是相对路径,且不能包含 `.`、`..` 或绝对路径段 +- `x-gframework-index` + - 为顶层必填、非主键、非引用的标量字段生成 `FindBy...` / `TryFindFirstBy...` 查找入口 +- `x-gframework-ref-table` + - 为字段补充跨表引用语义,并把这部分信息写入生成的绑定元数据 + +如果某个字段不满足 lookup index 的安全条件,生成器会直接报诊断,而不是静默生成一个容易失真的查询入口。 + +### 当前稳定约束子集 + +从源码和快照测试看,当前共享子集已经覆盖: + +- 标量、嵌套对象、对象数组、标量数组 +- `default`、`enum`、`const` +- `minimum`、`maximum`、`exclusiveMinimum`、`exclusiveMaximum`、`multipleOf` +- `minLength`、`maxLength`、`pattern` +- `format` + - 当前稳定字符串子集是 `date`、`date-time`、`duration`、`email`、`time`、`uri`、`uuid` +- `minItems`、`maxItems`、`uniqueItems`、`contains`、`minContains`、`maxContains` +- `minProperties`、`maxProperties` +- `dependentRequired`、`dependentSchemas`、`allOf` +- 面向对象约束的 `if` / `then` / `else` + +这些约束并不一定都会改变生成类型的形状,但会被保留到生成代码文档和绑定元数据里,方便运行时与工具链共享。 + +## 会生成什么 + +以 `monster.schema.json` 为例,当前生成器会形成四组稳定输出: + +### 1. 配置类型 + +例如 `MonsterConfig`。它承载 schema 字段到 C# 属性的映射,以及对应的 XML 文档。 + +### 2. 表包装类型 + +例如 `MonsterTable`。它包装运行时 `IConfigTable`,并在需要时提供生成的查找入口: + +```csharp +public sealed partial class MonsterTable : IConfigTable +{ + public MonsterConfig Get(int key) { ... } + + public IReadOnlyList FindByName(string value) { ... } + + public bool TryFindFirstByName(string value, out MonsterConfig? result) { ... } +} +``` + +如果字段声明了 `x-gframework-index`,生成器会优先使用延迟构建的只读索引;否则按当前表快照做确定性的线性扫描,以保持和热重载后的运行时数据一致。 + +### 3. 单表绑定辅助 + +例如 `MonsterConfigBindings`。这里会保留单表注册所需的表名、schema 路径、配置路径和引用元数据,方便项目侧继续组合自己的启动逻辑。 + +### 4. 聚合注册目录 + +当一个项目里有多个 schema 时,生成器还会汇总出 `GeneratedConfigCatalog` 与聚合扩展: + +```csharp +loader.RegisterAllGeneratedConfigTables(); +``` + +如果你需要按表传入额外比较器或做更细粒度控制,还可以使用带 `GeneratedConfigRegistrationOptions` 的重载。 + +## 运行时如何消费这些输出 + +最常见的消费路径是把生成器输出交给 `GameConfigBootstrap` 或 `YamlConfigLoader`: + +```csharp +using GFramework.Game.Config; +using GFramework.Game.Config.Generated; + +var bootstrap = new GameConfigBootstrap( + new GameConfigBootstrapOptions + { + RootPath = configRootPath, + ConfigureLoader = static loader => loader.RegisterAllGeneratedConfigTables() + }); +``` + +当你需要继续手动拼装运行时,也可以直接用单表绑定或聚合目录做自己的注册封装。这时建议把“启动生命周期”和“业务读取入口”分开,继续沿用 +[游戏内容配置系统](../game/config-system.md) 里的 `GameConfigHost` / `GameConfigRuntime` 模板。 + +## 常见诊断边界 + +当前 `ConfigSchemaDiagnostics` 暴露的错误主要分成四类: + +- schema 根对象或 JSON 读入失败 + - 例如 `GF_ConfigSchema_001`、`GF_ConfigSchema_002` +- 主键与类型映射不合法 + - 例如 `GF_ConfigSchema_003`、`GF_ConfigSchema_005` +- 生成标识符或路径元数据不安全 + - 例如 `GF_ConfigSchema_006`、`GF_ConfigSchema_007` +- 额外约束元数据不合法 + - 例如 `GF_ConfigSchema_008` 到 `GF_ConfigSchema_014` + +这些边界由 `GFramework.SourceGenerators.Tests/Config/SchemaConfigGeneratorTests.cs` 和快照测试共同覆盖。遇到生成失败时,优先先看诊断 ID,再回头核对 schema 本身是否超出当前公开子集。 + +## 什么时候优先看这页 + +适合: + +- 你想确认一个 schema 字段会生成哪些 C# 入口 +- 你要排查 `x-gframework-index`、路径元数据或标识符冲突 +- 你在做项目级聚合注册,希望知道 `GeneratedConfigCatalog` 和 `RegisterAllGeneratedConfigTables(...)` 的边界 + +不适合: + +- 你只是第一次接入配置运行时 +- 你更关心 `GameConfigBootstrap`、热重载、Godot 资源路径或 VS Code 配置工具 + +这些采用问题分别回到: + +- [游戏内容配置系统](../game/config-system.md) +- [VS Code 配置工具](../game/config-tool.md) +- [源码生成器总览](./index.md)