docs: @JsonExportFields 支持自动补 open(已实测)——非 open 类标注时宏自动加 open 修饰符
- 实测验证:宏展开的 open 在语义检查前生效,子类可正常继承 - 提供两种模式:默认自动补 open(推荐);requireOpen 严格模式非 open 报错 - 非 class 声明标注 → ASTException 编译期报错(已实测,错误定位到标注处) - 测试计划更新为对应三条用例
This commit is contained in:
+28
-8
@@ -189,9 +189,9 @@ public macro JsonExportFields(input: Tokens): Tokens {
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.1.1 open 校验(编译期报错)
|
||||
#### 3.1.1 open 处理(两种模式,默认自动补 open)
|
||||
|
||||
`@JsonExportFields` 的语义是「暴露**父类**字段给子类继承链」——标注在**非 open** 类上没有意义(非 open 类不能被继承,不存在子类实例传入的场景)。因此宏在展开时校验:
|
||||
`@JsonExportFields` 的语义是「暴露**父类**字段给子类继承链」——标注的类**必须可被继承**。Cangjie 类默认不可继承(非 open 类被继承会编译报错 `super class is not inheritable`),所以宏展开时处理 `open`:
|
||||
|
||||
```cangjie
|
||||
/// 遍历类声明的修饰符,检查是否含 open(参考 soulsoft Extensions.cj isOpen)
|
||||
@@ -203,17 +203,36 @@ func isOpenClass(decl: ClassDecl): Bool {
|
||||
}
|
||||
false
|
||||
}
|
||||
```
|
||||
|
||||
**模式一(推荐):自动补 open**
|
||||
|
||||
```cangjie
|
||||
// 宏展开入口内:
|
||||
if (!isOpenClass(decl)) {
|
||||
throw MacroException("@JsonExportFields 只能标注在 open class 上,"
|
||||
decl.modifiers.add(Modifier(Token(TokenKind.OPEN))) // 自动加 open
|
||||
}
|
||||
```
|
||||
|
||||
- **已实测可行**:宏给 `class Base` 自动加 `open` 后,子类 `class Child <: Base` 编译通过、正常运行(`macro_open_probe` 验证);
|
||||
- 宏展开的 `open` 在语义检查**之前**生效,所以后续继承检查能看到;
|
||||
- 用户少写一个关键字,标注 `@JsonExportFields` 本身就表达了「我要被继承」的意图。
|
||||
|
||||
**模式二:严格校验(不自动补,非 open 报错)**
|
||||
|
||||
```cangjie
|
||||
if (!isOpenClass(decl)) {
|
||||
throw ASTException("@JsonExportFields 只能标注在 open class 上,"
|
||||
+ "因为非 open 类不能被继承,不存在子类场景。")
|
||||
}
|
||||
```
|
||||
|
||||
- 抛 `MacroException` → 编译期直接报错,错误信息定位到标注处,用户立即发现;
|
||||
- 顺带校验:标注在 **struct / interface / enum / func** 等非 class 声明上也抛错(`MacroCallExpr<ClassDecl>.parse` 失败即报);
|
||||
- 参考先例:soulsoft `Extensions.cj:75-82` 就是遍历 `modifiers` 判 `TokenKind.OPEN`;宏内报错用 `std.ast` 的 `MacroException`(`assertion_macro.cj` 同款用法)。
|
||||
- 抛 `ASTException`(宏内实际可用异常类,soulsoft 同款)→ 编译期直接报错,错误定位到标注处(`main.cj:5:1` 形式);
|
||||
- 顺带校验:标注在 **struct / interface / enum / func** 等非 class 声明上也抛错(`parseDecl` 结果 `as ClassDecl` 失败即报,已实测)。
|
||||
|
||||
**取舍**:自动补 open 更省事但「隐式改变类语义」;严格校验更显式但要求用户记得写 `open`。默认建议模式一(自动补),可在宏属性中提供开关,如 `@JsonExportFields[requireOpen: true]` 切到模式二。
|
||||
|
||||
- 参考先例:soulsoft `Extensions.cj:75-82` 遍历 `modifiers` 判 `TokenKind.OPEN`;`SerializationMacro.cj:27` 用 `throw ASTException(...)` 做宏内校验;`cd.modifiers.add(Modifier(Token(TokenKind.OPEN)))` 与 soulsoft `funcDecl.modifiers.add(Modifier(Token(TokenKind.PUBLIC)))` 同款操作。
|
||||
|
||||
### 3.2 生成的目标代码
|
||||
|
||||
@@ -441,8 +460,9 @@ main() {
|
||||
| 父类字段 null | 导入时保持默认值 |
|
||||
| 与 @JsonPropertyName 组合 | 父类字段用注解名输出/匹配 |
|
||||
| 顶层序列化父类类型实例 | `Serialize(BaseUser 实例)` 直接可用 |
|
||||
| **宏校验:非 open 类标注报错** | 编译期报 `MacroException`(非 open class 标注 `@JsonExportFields` 编译失败) |
|
||||
| **宏校验:非 class 声明标注报错** | 对 struct/interface/enum 标注 `@JsonExportFields` 编译失败 |
|
||||
| **宏自动补 open** | `@JsonExportFields class Base`(无 open)展开后子类可继承(编译通过) |
|
||||
| **宏严格模式报错** | `@JsonExportFields[requireOpen: true]` 标注非 open class 编译失败 |
|
||||
| **宏非 class 标注报错** | 对 struct/interface/enum 标注 `@JsonExportFields` 编译失败 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user