Repository navigation
fix(config): give headless default values the field's type - #157
Conversation
The Mono.Cecil reflection provider read integer defaults straight from the IL constant, so byte, ushort and uint entries got int defaults. Editors that compare the default with a typed value (MaiChartManager's config save) saw every such entry as changed and wrote it out uncommented, e.g. GameSystem.Sound.BitsPerSample = 32. Defaults are now cast to the field type.
审阅者指南(小型 PR 中折叠显示)审阅者指南更新 headless/build-tool 反射,使整数支持字段的默认值以字段声明的原始类型返回,从而防止类型值比较错误地将未更改的配置项识别为已修改。 类型化配置默认值加载的时序图sequenceDiagram
participant Provider as MonoCecilReflectionProvider
participant IL as .cctor IL
participant Field as Config field
participant Consumer as Config consumer
Provider->>IL: 读取整数常量
IL-->>Provider: int32 或 int64 位
Provider->>Field: 获取类型代码(fieldType)
Provider->>Provider: 将位转换为声明的原始类型
Provider-->>Consumer: 类型化默认值
Consumer->>Consumer: 将实际值与类型化默认值进行比较
修正整数默认类型的流程图flowchart LR
A[整数 IL 常量] --> B{字段是原始类型吗?}
B -->|否| C[保留原始常量]
B -->|是| D[将位转换为字段原始类型]
D --> E[返回类型化默认值]
C --> E
E --> F[未更改的值不会被写入为已修改]
文件级变更
提示和命令与 Sourcery 交互
自定义使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's guide (collapsed on small PRs)Reviewer's GuideUpdates headless/build-tool reflection so integer-backed field defaults are returned with the field’s declared primitive type, preventing typed-value comparisons from falsely identifying unchanged configuration entries as modified. Sequence diagram for typed configuration default loadingsequenceDiagram
participant Provider as MonoCecilReflectionProvider
participant IL as .cctor IL
participant Field as Config field
participant Consumer as Config consumer
Provider->>IL: Read integer constant
IL-->>Provider: int32 or int64 bits
Provider->>Field: GetTypeCode(fieldType)
Provider->>Provider: Cast bits to declared primitive type
Provider-->>Consumer: Typed default value
Consumer->>Consumer: Compare actual value with typed default
Flow diagram for correcting integer default typesflowchart LR
A[Integer IL constant] --> B{Field is primitive?}
B -->|No| C[Keep original constant]
B -->|Yes| D[Convert bits to field primitive type]
D --> E[Return typed default]
C --> E
E --> F[Unchanged values are not written as modified]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
嘿——我发现了 1 个问题
给 AI 代理的提示
请处理本次代码审查中的评论:
## 单独评论
### 评论 1
<location path="AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs" line_range="145-155" />
<code_context>
+ defaultValue = Type.GetTypeCode(fieldType) switch
</code_context>
<issue_to_address>
**Char 默认值的类型不正确**
当 `[ConfigEntry]` `char` 字段使用整数常量初始化器时,`GetFieldDefaultValue` 会继续执行到 `loadOperand`,因此 `ReflectionField.Value`/`GetValue` 返回的是装箱后的 `int`,而 `FieldType` 是 `char`;类型化比较以及 `IReflectionProvider` 的无头模式或构建工具使用者会看到类型不匹配的默认值。
请在 switch 中处理 `TypeCode.Char`,将整数常量转换为 `char`。
另请检查 `AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs:156`。
</issue_to_address>Sourcery 评估
等待批准。 请先处理 1 个发现的问题。
阻塞性发现:AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs:155
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs" line_range="145-155" />
<code_context>
+ defaultValue = Type.GetTypeCode(fieldType) switch
</code_context>
<issue_to_address>
**Char defaults have wrong type**
When a `[ConfigEntry]` `char` field has an integer constant initializer, `GetFieldDefaultValue` falls through to `loadOperand`, so `ReflectionField.Value`/`GetValue` returns a boxed `int` while `FieldType` is `char`; typed comparisons and headless or build-tool consumers of `IReflectionProvider` see a mismatched default.
Handle `TypeCode.Char` in the switch by converting the integer constant to `char`.
Also at `AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs:156`.
</issue_to_address>Sourcery assessment
Approval pending. 1 finding to address first.
Blocking findings: AquaMai.Config/Reflection/MonoCecilAssemblyReflectionProvider.cs:155
There was a problem hiding this comment.
All reported issues were addressed across 1 file
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
|
草 这好像是我 mcm 注释里面存在了很久的未解之谜 |
MonoCecilReflectionProvider(used by the headless loader and the build tools) reads a field's default value from the IL constant in.cctor. IL pushes integer constants asint32, orint64afterconv.i8, whatever the field's type. Sobyte,ushortanduintentries gotintdefaults.This breaks any consumer that compares a typed value with the default. For example, MaiChartManager's config save treats
(ushort)32as different from(int)32, so it writes every such entry out uncommented as if the user had changed it:The fix casts integer constants to the field's primitive type. The cast is unchecked, because the constant holds the field's bits: for example,
uint 3000000000is pushed as-1294967296.boolkeeps its existing path, and non-integer constants are unchanged.Verification
I ran
MonoCecilReflectionProvideron the upstreamAquaMai.Mods.dll, before and after, counting[ConfigEntry]fields of primitive type whose default value's runtime type differs from the field type:GameSystem.SoundBitsPerSample / ValidBitsPerSample / SamplesPerSec,GameSettings.CreditConfig.LockCredits, all 34GameSettings.TouchSensitivityentries)MonoCecilReflectionProvider(HeadlessLoader 与构建工具使用)从.cctor的 IL 常量读取字段默认值。IL 总是以int32(conv.i8后为int64)压入整数常量,与字段类型无关,因此byte/ushort/uint配置项的默认值变成了int。比较默认值与实际值的工具(例如 MaiChartManager 保存配置)会把这些项都当作“已修改”,并以未注释的形式写出(如BitsPerSample = 32)。修复:把整数常量转换为字段的基本类型(unchecked,常量即字段的位模式)。验证:对上游
AquaMai.Mods.dll的 196 个基本类型配置项,默认值类型与字段类型不一致的数量从 38 降为 0。Sourcery 摘要
错误修复:
Original summary in English
Sourcery 摘要
错误修复:
Original summary in English
Summary by Sourcery
Bug Fixes: