diff --git a/src/main/java/com/codechecker/cache/analyze/FileScanner.java b/src/main/java/com/codechecker/cache/analyze/FileScanner.java index ba18b52..bff9c77 100644 --- a/src/main/java/com/codechecker/cache/analyze/FileScanner.java +++ b/src/main/java/com/codechecker/cache/analyze/FileScanner.java @@ -12,6 +12,7 @@ import java.util.stream.Stream; /** * 扫描工作树中受包含/排除模块限制的 {@code src/main/java} 下的所有 Java 源文件。 + *
返回路径 → 源码内容映射,供 {@link SchemaCheckAnalyzer} 构建新旧 {@code SourceIndex}。
*/ public class FileScanner { diff --git a/src/main/java/com/codechecker/cache/analyze/GlobMatcher.java b/src/main/java/com/codechecker/cache/analyze/GlobMatcher.java index 4001e47..1425316 100644 --- a/src/main/java/com/codechecker/cache/analyze/GlobMatcher.java +++ b/src/main/java/com/codechecker/cache/analyze/GlobMatcher.java @@ -10,6 +10,11 @@ public final class GlobMatcher { private GlobMatcher() { } + /** + * @param glob glob 模式(支持 {@code *} / {@code **}) + * @param input 待匹配字符串 + * @return 是否整串匹配 + */ public static boolean matches(String glob, String input) { if (glob == null || input == null) { return false; diff --git a/src/main/java/com/codechecker/cache/analyze/SchemaCheckAnalyzer.java b/src/main/java/com/codechecker/cache/analyze/SchemaCheckAnalyzer.java index 6f54356..34a5475 100644 --- a/src/main/java/com/codechecker/cache/analyze/SchemaCheckAnalyzer.java +++ b/src/main/java/com/codechecker/cache/analyze/SchemaCheckAnalyzer.java @@ -47,6 +47,14 @@ public class SchemaCheckAnalyzer { this.repoRoot = repoRoot; } + /** + * 对比两个提交之间的序列化结构变更。 + * + * @param oldSha 基准提交 + * @param newSha 当前提交(通常与工作树一致) + * @return 检测报告(含字段明细与按 Key/Topic 聚合结果) + * @throws GitException git 命令失败时 + */ public CheckReport analyze(String oldSha, String newSha) throws GitException { GitDiffScanner scanner = new GitDiffScanner(repoRoot); diff --git a/src/main/java/com/codechecker/cache/cli/SerializationSchemaCheckerMain.java b/src/main/java/com/codechecker/cache/cli/SerializationSchemaCheckerMain.java index 5f9c384..ddb8591 100644 --- a/src/main/java/com/codechecker/cache/cli/SerializationSchemaCheckerMain.java +++ b/src/main/java/com/codechecker/cache/cli/SerializationSchemaCheckerMain.java @@ -15,7 +15,9 @@ import java.util.List; import java.util.concurrent.Callable; /** - * 命令行入口。退出码:0 通过 / 1 阻断 / 2 执行错误。 + * 序列化结构检测工具的命令行入口(picocli)。 + *加载配置 → 对比 {@code old-sha}/{@code new-sha} → 控制台输出报告 → 可选企微通知。
+ *退出码:{@code 0} 通过或跳过;{@code 1} block 模式检测到变更;{@code 2} 执行错误。
*/ @Command(name = "serialization-schema-checker", mixinStandardHelpOptions = true, diff --git a/src/main/java/com/codechecker/cache/config/CheckerConfig.java b/src/main/java/com/codechecker/cache/config/CheckerConfig.java index 210dd37..315ec92 100644 --- a/src/main/java/com/codechecker/cache/config/CheckerConfig.java +++ b/src/main/java/com/codechecker/cache/config/CheckerConfig.java @@ -36,6 +36,7 @@ public class CheckerConfig { private List命中则不应建立写入点,避免对 String/数字等无结构缓存误报。
*/ final class BareValueTypes { @@ -21,10 +22,21 @@ final class BareValueTypes { private BareValueTypes() { } + /** + * 判断一个 Java 类型是否属于「无业务结构」的标量/裸类型集合。 + * + * @param simple simple + * @return boolean + */ static boolean isBareSimpleName(String simple) { return simple != null && BARE.contains(simple); } + /** + * 从 AST Type 取出简单名后调用 + * @param type type + * @return boolean + */ static boolean isBareType(Type type) { if (type == null) { return false; @@ -44,6 +56,11 @@ final class BareValueTypes { return "byte[]".equals(asString) || isBareSimpleName(asString); } + /** + * 从 FQN 截取最后一段再调用 + * @param fqn fqn + * @return boolean + */ static boolean isBareFqn(String fqn) { if (fqn == null || fqn.isEmpty()) { return false; diff --git a/src/main/java/com/codechecker/cache/detector/CacheReadHintDetector.java b/src/main/java/com/codechecker/cache/detector/CacheReadHintDetector.java index ec2b009..118597b 100644 --- a/src/main/java/com/codechecker/cache/detector/CacheReadHintDetector.java +++ b/src/main/java/com/codechecker/cache/detector/CacheReadHintDetector.java @@ -37,8 +37,6 @@ public class CacheReadHintDetector { "parseObject", "parse", "getJsonToBean", "toJavaObject", "readValue")); private static final Set
+ * 识别 {@code parseObject/parseArray/...} 且第 2 参为 {@code Xxx.class} 的调用,
+ * 解析出业务类型 FQN;若第 1 参能追溯到 Redis get,则附带 key 并将置信度提至 0.85,
+ * 否则仅保留类型提示(置信度 0.7)。结果供写入点类型补强,不单独告警。
+ */
private CacheReadHint tryParseHint(MethodCallExpr mce, String filePath) {
String name = mce.getNameAsString();
boolean array = ARRAY_PARSE.contains(name);
@@ -98,6 +110,7 @@ public class CacheReadHintDetector {
: enclosing.getFullyQualifiedName().orElse(enclosing.getNameAsString());
SourceIndex.IndexedType context = index.get(enclosingFqn);
+ // 优先带包前缀解析(如 com.foo.Bar.class),失败再退回简单类名 + import/同包
String fqn = index.resolveFqn(((ClassOrInterfaceType) type).getNameWithScope(), context);
if (fqn == null) {
fqn = index.resolveFqn(((ClassOrInterfaceType) type).getNameAsString(), context);
@@ -116,12 +129,12 @@ public class CacheReadHintDetector {
hint.setRootArray(array || "parseArray".equals(name) || "getJsonToList".equals(name));
hint.setConfidence(0.7);
+ // 第 1 参:原始 JSON 字符串;能关联到 redis.get(key) 时补 key,便于与写入点按 key 匹配
Expression rawExpr = mce.getArgument(0);
Optional
+ * 覆盖常见形态:{@code redisUtil.get/getString(key)}、
+ * {@code redisTemplate.opsForValue().get(key)}、{@code boundValueOps.get(key)}。
+ * {@code getString} 即使接收者名不含 redis 也接受(RedisUtil 习惯命名);
+ * 普通 {@code get} 依赖 scope 命中 redis / opsForValue / boundValueOps 启发式。
+ * 无法识别时返回 empty,不抛错。
+ */
private Optional 用于 Diff 结果分类与报告展示标签;实际严重级别可被 {@code severity_overrides} 覆盖。 由 {@link SchemaDiffer} 或分析器在「新增/删除写入点」时生成,再进入报告明细。 Webhook 为空时跳过;HTTP/errcode 失败时打 stderr 日志并返回 false。
+ *
*/
public enum Severity {
+ /** 高危结构破坏 */
P0,
+ /** 中危兼容性风险 */
P1,
+ /** 低危或需人工确认 */
P2
}
diff --git a/src/main/java/com/codechecker/cache/git/GitException.java b/src/main/java/com/codechecker/cache/git/GitException.java
index a0540e4..43eb3f1 100644
--- a/src/main/java/com/codechecker/cache/git/GitException.java
+++ b/src/main/java/com/codechecker/cache/git/GitException.java
@@ -1,14 +1,16 @@
package com.codechecker.cache.git;
/**
- * Git 操作异常。
+ * Git 命令执行失败时抛出的受检异常(如 {@code git diff}/{@code git show} 非零退出)。
*/
public class GitException extends Exception {
+ /** @param message 失败说明(通常含命令与 stderr 摘要) */
public GitException(String message) {
super(message);
}
+ /** @param message 失败说明 @param cause 底层原因 */
public GitException(String message, Throwable cause) {
super(message, cause);
}
diff --git a/src/main/java/com/codechecker/cache/key/RedisKeyResolver.java b/src/main/java/com/codechecker/cache/key/RedisKeyResolver.java
index 8052dcc..86bb80c 100644
--- a/src/main/java/com/codechecker/cache/key/RedisKeyResolver.java
+++ b/src/main/java/com/codechecker/cache/key/RedisKeyResolver.java
@@ -32,6 +32,14 @@ public class RedisKeyResolver {
this.index = index;
}
+ /**
+ * 将 key / destination 表达式推断为静态模式字符串。
+ *
+ * @param keyExpr AST 表达式(字面量、常量拼接、format 等)
+ * @param enclosingClass 所在类(用于查常量/方法)
+ * @param context 类型索引上下文,可为 {@code null}
+ * @return 规范化模式;动态段为 {@code *},无法推断时多为 {@code *} 或 {@code unknown-key} 上游处理
+ */
public String resolve(Expression keyExpr, ClassOrInterfaceDeclaration enclosingClass,
SourceIndex.IndexedType context) {
String raw = resolveExpr(keyExpr, enclosingClass, context, 0);
diff --git a/src/main/java/com/codechecker/cache/notify/WeComNotifier.java b/src/main/java/com/codechecker/cache/notify/WeComNotifier.java
index e18224c..5a36a5d 100644
--- a/src/main/java/com/codechecker/cache/notify/WeComNotifier.java
+++ b/src/main/java/com/codechecker/cache/notify/WeComNotifier.java
@@ -13,7 +13,8 @@ import java.util.List;
import java.util.Map;
/**
- * 企业微信群机器人通知(markdown 消息)。
+ * 企业微信群机器人通知:发送 markdown 消息(单条或多条按序发送)。
+ *