feat: V1.1 - 注释补充
This commit is contained in:
198
docs/工程结构.md
Normal file
198
docs/工程结构.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# 序列化结构检测器 — 工程结构说明
|
||||||
|
|
||||||
|
> 工程:`serialization-schema-checker`(`com.codechecker:serialization-schema-checker`)
|
||||||
|
> 定位:基于 JavaParser 的 **Redis 缓存 / MQ(RocketMQ、Kafka)value 序列化结构变更** 静态检测工具
|
||||||
|
> 当前版本:`1.1.0` · Java 11 · 可执行 Fat Jar(maven-shade)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 仓库顶层结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
redisCheck/
|
||||||
|
├── pom.xml # Maven 单模块工程
|
||||||
|
├── .gitea/ # Gitea Actions 与示例/自检配置
|
||||||
|
│ ├── workflows/
|
||||||
|
│ │ └── serialization-schema-check.yaml
|
||||||
|
│ └── config/
|
||||||
|
│ └── serialization-schema-check-config.yaml
|
||||||
|
├── docs/ # 方案、配置与集成文档(本目录)
|
||||||
|
├── src/
|
||||||
|
│ ├── main/
|
||||||
|
│ │ ├── java/com/codechecker/cache/ # 主代码(按职责分包)
|
||||||
|
│ │ └── resources/
|
||||||
|
│ │ └── default-config.yaml # jar 内置默认配置
|
||||||
|
│ └── test/
|
||||||
|
│ ├── java/com/codechecker/cache/ # 单测 / 场景测
|
||||||
|
│ └── resources/fixtures/ # 源码片段夹具
|
||||||
|
└── target/ # 构建产物(不入库)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 主代码包结构
|
||||||
|
|
||||||
|
根包:`com.codechecker.cache`
|
||||||
|
|
||||||
|
```text
|
||||||
|
com.codechecker.cache
|
||||||
|
├── cli/ # 命令行入口
|
||||||
|
├── config/ # 配置模型与加载
|
||||||
|
├── git/ # Git diff / show 封装
|
||||||
|
├── analyze/ # 扫描编排与主分析流程
|
||||||
|
├── detector/ # 写入点 / 读侧提示检测
|
||||||
|
├── key/ # Redis key 表达式解析
|
||||||
|
├── schema/ # 类型索引、字段 Schema、骨架 JSON
|
||||||
|
├── diff/ # Schema Diff 与变更类型
|
||||||
|
├── report/ # 报告模型与渲染
|
||||||
|
└── notify/ # 企微机器人通知
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.1 包职责与主要类
|
||||||
|
|
||||||
|
| 包 | 职责 | 主要类 |
|
||||||
|
|----|------|--------|
|
||||||
|
| **cli** | picocli 入口;加载配置 → 分析 → 控制台报告 → 可选通知 | `SerializationSchemaCheckerMain` |
|
||||||
|
| **config** | 默认配置与业务配置深度合并;运行时配置模型 | `ConfigLoader`、`CheckerConfig` |
|
||||||
|
| **git** | 变更 Java 文件列表、按 SHA 取文件内容 | `GitDiffScanner`、`GitException` |
|
||||||
|
| **analyze** | 端到端编排:候选文件 → 写点检测 → Schema 提取 → Diff → 报告 | `SchemaCheckAnalyzer`、`FileScanner`、`GlobMatcher` |
|
||||||
|
| **detector** | 识别 Redis/MQ 写入(投递)点与读侧类型提示 | `RedisWritePointDetector`、`MqWritePointDetector`、`CacheReadHintDetector`、`MqReadHintDetector`、`BareValueTypes`、`WritePoint`、`CacheReadHint` |
|
||||||
|
| **key** | 将 key 表达式解析为模式(如 `demo:foo:*`) | `RedisKeyResolver` |
|
||||||
|
| **schema** | 源码类型索引、字段展开、骨架 JSON 渲染 | `SourceIndex`、`JavaSchemaExtractor`、`TypeSchema`、`FieldSchema`、`SkeletonJsonRenderer`、`AnnotationSupport`、`JsonType` |
|
||||||
|
| **diff** | 新旧 Schema 对比,产出变更明细 | `SchemaDiffer`、`SchemaChange`、`ChangeType`、`Severity` |
|
||||||
|
| **report** | 按 Key/Topic 聚合、企微 Markdown / 控制台文本 | `CheckReport`、`KeyStructureChange`、`ReportBuilder`、`SkeletonAnnotator` |
|
||||||
|
| **notify** | 企微机器人 Webhook 发送 | `WeComNotifier` |
|
||||||
|
|
||||||
|
### 2.2 核心数据模型(实体)
|
||||||
|
|
||||||
|
| 类 | 含义 |
|
||||||
|
|----|------|
|
||||||
|
| `WritePoint` | 一处 Redis 写入或 MQ 投递点(通道、key/topic、value 类型、位置) |
|
||||||
|
| `CacheReadHint` | 读侧反序列化推断出的类型提示(补强写入点,不单独告警) |
|
||||||
|
| `TypeSchema` / `FieldSchema` | value 类型展开后的扁平 Schema |
|
||||||
|
| `SchemaChange` | 单条结构变更(类型、路径、严重级别、说明) |
|
||||||
|
| `KeyStructureChange` | 按 Key/Topic 聚合的摘要(含前后骨架 JSON) |
|
||||||
|
| `CheckReport` | 一次检测的完整结果 |
|
||||||
|
| `CheckerConfig` | 运行配置(含 Notify / Ignore / Detection 等嵌套结构) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 运行时数据流
|
||||||
|
|
||||||
|
```text
|
||||||
|
SerializationSchemaCheckerMain
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
ConfigLoader.load(--config)
|
||||||
|
│ jar 内 default-config.yaml ⊕ 业务配置
|
||||||
|
▼
|
||||||
|
SchemaCheckAnalyzer.analyze(oldSha, newSha)
|
||||||
|
│
|
||||||
|
├─ GitDiffScanner → 变更 .java 文件
|
||||||
|
├─ FileScanner → 读新旧源码内容
|
||||||
|
├─ SourceIndex → 建类型索引
|
||||||
|
├─ Redis/Mq WritePointDetector → 写入/投递点
|
||||||
|
├─ Cache/Mq ReadHintDetector → 读侧类型补强
|
||||||
|
├─ JavaSchemaExtractor → 展开 TypeSchema
|
||||||
|
├─ SchemaDiffer → SchemaChange 列表
|
||||||
|
└─ 聚合 KeyStructureChange → CheckReport
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
ReportBuilder (控制台 + 企微 Markdown)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
WeComNotifier (可选,--dry-run 时跳过)
|
||||||
|
```
|
||||||
|
|
||||||
|
**退出码约定**
|
||||||
|
|
||||||
|
| 码 | 含义 |
|
||||||
|
|----|------|
|
||||||
|
| `0` | 通过、跳过(`enabled=false` / 无基准 SHA)或 notify 模式有变更 |
|
||||||
|
| `1` | `mode=block` 且检测到结构变更 |
|
||||||
|
| `2` | 执行异常 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 资源与配置
|
||||||
|
|
||||||
|
| 路径 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `src/main/resources/default-config.yaml` | 工具内置默认:检测模式、忽略规则、严重级别等 |
|
||||||
|
| 业务仓 `.gitea/config/serialization-schema-check-config.yaml` | 业务覆盖配置(流水线 `--config` 指向) |
|
||||||
|
| 本仓 `.gitea/config/serialization-schema-check-config.yaml` | 工具仓自用/示例配置 |
|
||||||
|
|
||||||
|
配置合并与字段说明见:[配置说明.md](./配置说明.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 测试结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/test/java/com/codechecker/cache/
|
||||||
|
├── TestSupport.java # 夹具加载等公共方法
|
||||||
|
├── *ScenarioTest.java # 端到端场景(tenant / mq / recording-todo)
|
||||||
|
├── analyze/ / config/ / detector/
|
||||||
|
├── diff/ / key/ / report/ / schema/ # 与主包对应的单测
|
||||||
|
└── ...
|
||||||
|
|
||||||
|
src/test/resources/fixtures/
|
||||||
|
├── lock/ # 分布式锁等非结构写入样例
|
||||||
|
├── template/ # 模板写入样例
|
||||||
|
├── tenant/ # 包装层 / 字段迁移场景
|
||||||
|
├── recording-todo/ # Redis 写入场景
|
||||||
|
└── mq/
|
||||||
|
├── kafka-patrol/ # Kafka 巡检相关
|
||||||
|
├── kafka-record/ # Kafka Record 投递/消费
|
||||||
|
├── rocket-im/ # RocketMQ IM 通知
|
||||||
|
└── rocket-wallet/ # RocketMQ 钱包扣款
|
||||||
|
```
|
||||||
|
|
||||||
|
夹具多为 `.txt` 形式的 Java 源码片段,由场景测试拼装为新旧版本对比输入。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 构建与产物
|
||||||
|
|
||||||
|
| 项 | 说明 |
|
||||||
|
|----|------|
|
||||||
|
| 构建 | `mvn clean package` |
|
||||||
|
| 主类 | `com.codechecker.cache.cli.SerializationSchemaCheckerMain` |
|
||||||
|
| 产物 | `target/serialization-schema-checker-1.1.0.jar`(shade 可执行包) |
|
||||||
|
| 主要依赖 | JavaParser、SnakeYAML、Jackson、picocli、Lombok(provided)、JUnit 5(test) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 文档索引
|
||||||
|
|
||||||
|
| 文档 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| [工程结构.md](./工程结构.md) | 本文:目录与模块职责 |
|
||||||
|
| [配置说明.md](./配置说明.md) | 配置项、合并规则、忽略/抑制 |
|
||||||
|
| [CI集成说明.md](./CI集成说明.md) | 流水线接入方式 |
|
||||||
|
| [v1.0/](./v1.0/) | Redis / MQ 检测实施方案(历史方案) |
|
||||||
|
| [V1.1/](./V1.1/) | 非结构写入收敛、新增写入点展示等整改方案 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 模块依赖关系(简图)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
CLI[cli] --> CFG[config]
|
||||||
|
CLI --> AN[analyze]
|
||||||
|
CLI --> RPT[report]
|
||||||
|
CLI --> NT[notify]
|
||||||
|
AN --> GIT[git]
|
||||||
|
AN --> DET[detector]
|
||||||
|
AN --> SCH[schema]
|
||||||
|
AN --> DIFF[diff]
|
||||||
|
AN --> RPT
|
||||||
|
DET --> KEY[key]
|
||||||
|
DET --> SCH
|
||||||
|
DIFF --> SCH
|
||||||
|
RPT --> DIFF
|
||||||
|
NT --> RPT
|
||||||
|
```
|
||||||
|
|
||||||
|
上层调用下层;`detector` / `schema` / `diff` 不依赖 `cli` 与 `notify`,便于单测与复用。
|
||||||
@@ -16,27 +16,37 @@ public class CheckerConfig {
|
|||||||
/** 总开关:false 时跳过检测与通知(流水线 exit 0) */
|
/** 总开关:false 时跳过检测与通知(流水线 exit 0) */
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
|
|
||||||
/** notify | block */
|
/** 运行模式:notify(仅通知)| block(有变更则失败退出) */
|
||||||
private String mode = "notify";
|
private String mode = "notify";
|
||||||
|
|
||||||
|
/** 是否扫描 test 源码目录 */
|
||||||
private boolean scanTestSources = false;
|
private boolean scanTestSources = false;
|
||||||
|
|
||||||
|
/** 额外源码根路径(相对仓库根);空则按约定扫描 main */
|
||||||
private List<String> sourceRoots = new ArrayList<>();
|
private List<String> sourceRoots = new ArrayList<>();
|
||||||
|
|
||||||
|
/** 企微通知配置 */
|
||||||
private Notify notify = new Notify();
|
private Notify notify = new Notify();
|
||||||
|
|
||||||
|
/** 忽略规则(key / 文件 / 写入方法 / MQ destination) */
|
||||||
private Ignore ignore = new Ignore();
|
private Ignore ignore = new Ignore();
|
||||||
|
|
||||||
|
/** 检测模式与推断参数 */
|
||||||
private Detection detection = new Detection();
|
private Detection detection = new Detection();
|
||||||
|
|
||||||
|
/** 按 ChangeType 名覆盖默认严重级别,如 FIELD_ADDED → P0 */
|
||||||
private Map<String, String> severityOverrides = new LinkedHashMap<>();
|
private Map<String, String> severityOverrides = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
/** 人工写入点映射(自动推断不准时补齐) */
|
||||||
private List<ManualMapping> manualMappings = new ArrayList<>();
|
private List<ManualMapping> manualMappings = new ArrayList<>();
|
||||||
|
|
||||||
|
/** 已知误报抑制规则 */
|
||||||
private List<Suppression> suppressions = new ArrayList<>();
|
private List<Suppression> suppressions = new ArrayList<>();
|
||||||
|
|
||||||
|
/** 仅检测这些模块(路径前缀/模块名);空表示不限制 */
|
||||||
private List<String> includeModules = new ArrayList<>();
|
private List<String> includeModules = new ArrayList<>();
|
||||||
|
|
||||||
|
/** 排除这些模块,不参与检测 */
|
||||||
private List<String> excludeModules = new ArrayList<>();
|
private List<String> excludeModules = new ArrayList<>();
|
||||||
|
|
||||||
public boolean isBlockMode() {
|
public boolean isBlockMode() {
|
||||||
@@ -46,18 +56,24 @@ public class CheckerConfig {
|
|||||||
/** 企微通知相关配置。 */
|
/** 企微通知相关配置。 */
|
||||||
@Data
|
@Data
|
||||||
public static class Notify {
|
public static class Notify {
|
||||||
|
/** 是否发送企微通知 */
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
/** 企微机器人 Webhook 完整 URL */
|
/** 企微机器人 Webhook 完整 URL */
|
||||||
private String webhookUrl = "";
|
private String webhookUrl = "";
|
||||||
|
/** 无变更时是否仍发「清洁」通知 */
|
||||||
private boolean notifyOnClean = false;
|
private boolean notifyOnClean = false;
|
||||||
|
/** 报告标题前缀 */
|
||||||
private String titlePrefix = "[序列化结构变更]";
|
private String titlePrefix = "[序列化结构变更]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 忽略规则:key / 文件路径 / 写入方法 / MQ destination。 */
|
/** 忽略规则:key / 文件路径 / 写入方法 / MQ destination。 */
|
||||||
@Data
|
@Data
|
||||||
public static class Ignore {
|
public static class Ignore {
|
||||||
|
/** 忽略的 Redis key / 模式 */
|
||||||
private List<String> keyPatterns = new ArrayList<>();
|
private List<String> keyPatterns = new ArrayList<>();
|
||||||
|
/** 忽略的源文件 glob */
|
||||||
private List<String> filePatterns = new ArrayList<>();
|
private List<String> filePatterns = new ArrayList<>();
|
||||||
|
/** 忽略的写入方法(Class#method 或简单名) */
|
||||||
private List<String> writerMethods = new ArrayList<>();
|
private List<String> writerMethods = new ArrayList<>();
|
||||||
/** 忽略的 MQ destination 模式(topic / topic:tag) */
|
/** 忽略的 MQ destination 模式(topic / topic:tag) */
|
||||||
private List<String> mqDestinations = new ArrayList<>();
|
private List<String> mqDestinations = new ArrayList<>();
|
||||||
@@ -66,10 +82,13 @@ public class CheckerConfig {
|
|||||||
/** 检测模式与推断参数(Redis W*、MQ MQ*、读侧补强开关等)。 */
|
/** 检测模式与推断参数(Redis W*、MQ MQ*、读侧补强开关等)。 */
|
||||||
@Data
|
@Data
|
||||||
public static class Detection {
|
public static class Detection {
|
||||||
|
/** Redis 写入检测模式列表,如 W01~W06 */
|
||||||
private List<String> patterns = new ArrayList<>();
|
private List<String> patterns = new ArrayList<>();
|
||||||
/** MQ 投递检测模式:MQ01~MQ05、MQ-K01~MQ-K04 */
|
/** MQ 投递检测模式:MQ01~MQ05、MQ-K01~MQ-K04 */
|
||||||
private List<String> mqPatterns = new ArrayList<>();
|
private List<String> mqPatterns = new ArrayList<>();
|
||||||
|
/** 低于此置信度的结构变更按低置信度降级处理 */
|
||||||
private double minConfidence = 0.6;
|
private double minConfidence = 0.6;
|
||||||
|
/** 字段展开最大深度,防止循环引用爆栈 */
|
||||||
private int maxFieldDepth = 8;
|
private int maxFieldDepth = 8;
|
||||||
/** W06:是否启用读侧反序列化类型辅助补强 */
|
/** W06:是否启用读侧反序列化类型辅助补强 */
|
||||||
private boolean readHintsEnabled = true;
|
private boolean readHintsEnabled = true;
|
||||||
@@ -82,10 +101,15 @@ public class CheckerConfig {
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public static class ManualMapping {
|
public static class ManualMapping {
|
||||||
|
/** 规则 id(便于配置追溯) */
|
||||||
private String id;
|
private String id;
|
||||||
|
/** 目标写入方法标识 */
|
||||||
private String writerMethod;
|
private String writerMethod;
|
||||||
|
/** 指定的 key / destination 模式 */
|
||||||
private String keyPattern;
|
private String keyPattern;
|
||||||
|
/** 指定的 value 类型 */
|
||||||
private String valueType;
|
private String valueType;
|
||||||
|
/** 备注说明 */
|
||||||
private String description;
|
private String description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,10 +118,15 @@ public class CheckerConfig {
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public static class Suppression {
|
public static class Suppression {
|
||||||
|
/** 规则 id */
|
||||||
private String id;
|
private String id;
|
||||||
|
/** 可选:限定写入方法 */
|
||||||
private String writerMethod;
|
private String writerMethod;
|
||||||
|
/** 可选:匹配的 key / destination 模式 */
|
||||||
private String keyPattern;
|
private String keyPattern;
|
||||||
|
/** 要抑制的 ChangeType 名列表;空表示不按类型过滤 */
|
||||||
private List<String> changeTypes = new ArrayList<>();
|
private List<String> changeTypes = new ArrayList<>();
|
||||||
|
/** 抑制原因(文档用) */
|
||||||
private String reason;
|
private String reason;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,22 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class CacheReadHint {
|
public class CacheReadHint {
|
||||||
|
|
||||||
|
/** 源文件相对路径 */
|
||||||
private String filePath;
|
private String filePath;
|
||||||
|
/** 反序列化调用所在行号 */
|
||||||
private int lineNumber;
|
private int lineNumber;
|
||||||
|
/** 所在类 FQN */
|
||||||
private String enclosingClass;
|
private String enclosingClass;
|
||||||
|
/** 所在方法名 */
|
||||||
private String enclosingMethod;
|
private String enclosingMethod;
|
||||||
/** 推断出的 key 模式;无法关联 redis get 时为 null */
|
/** 推断出的 key 模式;无法关联 redis get 时为 null */
|
||||||
private String resolvedKeyPattern;
|
private String resolvedKeyPattern;
|
||||||
|
/** 源码中的 key 表达式原文 */
|
||||||
private String keyExpression;
|
private String keyExpression;
|
||||||
/** value 元素/对象 FQN */
|
/** value 元素/对象 FQN */
|
||||||
private String resolvedValueType;
|
private String resolvedValueType;
|
||||||
|
/** 是否按数组根(parseArray / getJsonToList 等)理解 value */
|
||||||
private boolean rootArray;
|
private boolean rootArray;
|
||||||
|
/** 提示置信度:仅有类型约 0.7,关联到 redis get 约 0.85 */
|
||||||
private double confidence = 0.7;
|
private double confidence = 0.7;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,23 +10,37 @@ import lombok.Setter;
|
|||||||
@Data
|
@Data
|
||||||
public class WritePoint {
|
public class WritePoint {
|
||||||
|
|
||||||
|
/** Redis 通道标识 */
|
||||||
public static final String CHANNEL_REDIS = "REDIS";
|
public static final String CHANNEL_REDIS = "REDIS";
|
||||||
|
/** RocketMQ 通道标识 */
|
||||||
public static final String CHANNEL_ROCKETMQ = "ROCKETMQ";
|
public static final String CHANNEL_ROCKETMQ = "ROCKETMQ";
|
||||||
|
/** Kafka 通道标识 */
|
||||||
public static final String CHANNEL_KAFKA = "KAFKA";
|
public static final String CHANNEL_KAFKA = "KAFKA";
|
||||||
|
|
||||||
|
/** 源文件相对路径 */
|
||||||
private String filePath;
|
private String filePath;
|
||||||
|
/** 写入/投递调用所在行号 */
|
||||||
private int lineNumber;
|
private int lineNumber;
|
||||||
|
/** 所在类 FQN */
|
||||||
private String enclosingClass;
|
private String enclosingClass;
|
||||||
|
/** 所在方法名 */
|
||||||
private String enclosingMethod;
|
private String enclosingMethod;
|
||||||
|
/** 命中的检测模式编号,如 W01、MQ01、MQ-K01 */
|
||||||
private String pattern;
|
private String pattern;
|
||||||
|
|
||||||
|
/** 源码中的 key / destination 表达式 */
|
||||||
private String keyExpression;
|
private String keyExpression;
|
||||||
|
/** 解析后的 key / Topic 模式(如 demo:foo:*) */
|
||||||
private String resolvedKeyPattern;
|
private String resolvedKeyPattern;
|
||||||
|
|
||||||
|
/** 源码中的 value 表达式 */
|
||||||
private String valueExpression;
|
private String valueExpression;
|
||||||
|
/** 推断的 value 类型 FQN */
|
||||||
private String resolvedValueType;
|
private String resolvedValueType;
|
||||||
|
/** value 是否为数组根(List / 数组序列化) */
|
||||||
private boolean rootArray;
|
private boolean rootArray;
|
||||||
|
|
||||||
|
/** 类型/key 推断置信度,默认 1.0 */
|
||||||
private double confidence = 1.0;
|
private double confidence = 1.0;
|
||||||
|
|
||||||
/** REDIS / ROCKETMQ / KAFKA;默认 REDIS 兼容现网 */
|
/** REDIS / ROCKETMQ / KAFKA;默认 REDIS 兼容现网 */
|
||||||
|
|||||||
@@ -9,15 +9,25 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class SchemaChange {
|
public class SchemaChange {
|
||||||
|
|
||||||
|
/** 严重级别(可由 severity_overrides 覆盖默认值) */
|
||||||
private Severity severity;
|
private Severity severity;
|
||||||
|
/** 变更类型(字段增删、包装层、写入点增删等) */
|
||||||
private ChangeType changeType;
|
private ChangeType changeType;
|
||||||
|
/** 解析后的 key / Topic 模式 */
|
||||||
private String keyPattern;
|
private String keyPattern;
|
||||||
|
/** 源码中的 key / destination 表达式 */
|
||||||
private String keyExpression;
|
private String keyExpression;
|
||||||
|
/** 写入位置,形如 Class#method:line */
|
||||||
private String writeLocation;
|
private String writeLocation;
|
||||||
|
/** 展示用 value 类型名 */
|
||||||
private String valueType;
|
private String valueType;
|
||||||
|
/** 字段路径(点分,数组用 []),写入点级变更可为空 */
|
||||||
private String fieldPath;
|
private String fieldPath;
|
||||||
|
/** 变更前取值说明(类型名、路径等,依 changeType 而定) */
|
||||||
private String oldValue;
|
private String oldValue;
|
||||||
|
/** 变更后取值说明 */
|
||||||
private String newValue;
|
private String newValue;
|
||||||
|
/** 人可读变更说明,用于报告明细 */
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public SchemaChange(ChangeType changeType) {
|
public SchemaChange(ChangeType changeType) {
|
||||||
|
|||||||
@@ -14,17 +14,28 @@ import java.util.List;
|
|||||||
@Data
|
@Data
|
||||||
public class CheckReport {
|
public class CheckReport {
|
||||||
|
|
||||||
|
/** 仓库名(报告抬头展示) */
|
||||||
private String repository;
|
private String repository;
|
||||||
|
/** 分支名 */
|
||||||
private String branch;
|
private String branch;
|
||||||
|
/** 对比基准提交 SHA */
|
||||||
private String oldSha;
|
private String oldSha;
|
||||||
|
/** 当前提交 SHA */
|
||||||
private String newSha;
|
private String newSha;
|
||||||
|
/** 提交人 */
|
||||||
private String modifier;
|
private String modifier;
|
||||||
|
/** 提交时间(展示用字符串) */
|
||||||
private String modifyTime;
|
private String modifyTime;
|
||||||
|
/** 运行模式:notify / block */
|
||||||
private String mode;
|
private String mode;
|
||||||
|
|
||||||
|
/** 字段级变更明细(去重、抑制后) */
|
||||||
private final List<SchemaChange> changes = new ArrayList<>();
|
private final List<SchemaChange> changes = new ArrayList<>();
|
||||||
|
/** 按 Key/Topic 聚合的结构变更摘要 */
|
||||||
private final List<KeyStructureChange> keyChanges = new ArrayList<>();
|
private final List<KeyStructureChange> keyChanges = new ArrayList<>();
|
||||||
|
/** block 模式下是否应阻断流水线 */
|
||||||
private boolean blocked;
|
private boolean blocked;
|
||||||
|
/** 建议进程退出码:0 通过,1 阻断,2 执行错误 */
|
||||||
private int exitCode;
|
private int exitCode;
|
||||||
|
|
||||||
/** @return 是否存在字段级或 Key 级结构变更 */
|
/** @return 是否存在字段级或 Key 级结构变更 */
|
||||||
|
|||||||
@@ -23,13 +23,18 @@ public class KeyStructureChange {
|
|||||||
private String writeLocation;
|
private String writeLocation;
|
||||||
/** 展示用 value 类型,如 List<ClockInExportVo> */
|
/** 展示用 value 类型,如 List<ClockInExportVo> */
|
||||||
private String valueType;
|
private String valueType;
|
||||||
|
/** key 是否未能静态解析(报告中标灰提示) */
|
||||||
private boolean keyUnresolved;
|
private boolean keyUnresolved;
|
||||||
/** REDIS / ROCKETMQ / KAFKA */
|
/** REDIS / ROCKETMQ / KAFKA */
|
||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
private String channel = "REDIS";
|
private String channel = "REDIS";
|
||||||
|
/** 变更前序列化骨架 JSON(已删除写入/投递时仅有此项) */
|
||||||
private String oldSkeletonJson;
|
private String oldSkeletonJson;
|
||||||
|
/** 变更后序列化骨架 JSON(新增写入/投递时仅有此项) */
|
||||||
private String newSkeletonJson;
|
private String newSkeletonJson;
|
||||||
|
/** 本聚合块最高严重级别 */
|
||||||
private Severity severity = Severity.P2;
|
private Severity severity = Severity.P2;
|
||||||
|
/** 归属本 Key/Topic 的字段级变更明细 */
|
||||||
private final List<SchemaChange> fieldDetails = new ArrayList<>();
|
private final List<SchemaChange> fieldDetails = new ArrayList<>();
|
||||||
|
|
||||||
public void setChannel(String channel) {
|
public void setChannel(String channel) {
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ import lombok.Value;
|
|||||||
@Value
|
@Value
|
||||||
public class FieldSchema {
|
public class FieldSchema {
|
||||||
|
|
||||||
|
/** 字段路径,如 {@code vo.linkList[].id} */
|
||||||
String path;
|
String path;
|
||||||
|
/** 映射到的 JSON 类型(OBJECT / ARRAY / STRING 等) */
|
||||||
JsonType jsonType;
|
JsonType jsonType;
|
||||||
|
/** 原始 Java 类型简单名或 FQN 片段 */
|
||||||
String javaType;
|
String javaType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -178,9 +178,13 @@ public class SourceIndex {
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||||
public static final class IndexedType {
|
public static final class IndexedType {
|
||||||
|
/** 类型 AST 声明 */
|
||||||
private final ClassOrInterfaceDeclaration declaration;
|
private final ClassOrInterfaceDeclaration declaration;
|
||||||
|
/** 所在包名(无包则为空串) */
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
|
/** 文件 import 列表(含通配 import.*) */
|
||||||
private final List<String> imports;
|
private final List<String> imports;
|
||||||
|
/** 类型 FQN(含内部类,以 . 分隔) */
|
||||||
private final String fqn;
|
private final String fqn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import java.util.Map;
|
|||||||
@Getter
|
@Getter
|
||||||
public class TypeSchema {
|
public class TypeSchema {
|
||||||
|
|
||||||
|
/** 根 value 类型 FQN(或展示名) */
|
||||||
private final String rootType;
|
private final String rootType;
|
||||||
|
/** Schema 展开置信度;类型解析不完整时会下调 */
|
||||||
@Setter
|
@Setter
|
||||||
private double confidence = 1.0;
|
private double confidence = 1.0;
|
||||||
|
/** path → 字段节点(插入顺序保留) */
|
||||||
private final Map<String, FieldSchema> fields = new LinkedHashMap<>();
|
private final Map<String, FieldSchema> fields = new LinkedHashMap<>();
|
||||||
|
|
||||||
public TypeSchema(String rootType) {
|
public TypeSchema(String rootType) {
|
||||||
|
|||||||
Reference in New Issue
Block a user