项目结构变更

This commit is contained in:
2026-06-09 11:20:24 +08:00
parent fb6cd124c8
commit 871823b3da
45 changed files with 222 additions and 223 deletions

View File

@@ -0,0 +1,57 @@
package com.codechecker.model;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* 索引中的 HTTP/Feign 接口方法、URI、入参/返回类型简单名。
*/
public class ApiEndpoint {
private final String httpMethod;
private final String uri;
private final String sourceFile;
private final Set<String> paramTypes;
private final Set<String> returnTypes;
public ApiEndpoint(String httpMethod, String uri, String sourceFile,
Set<String> paramTypes, Set<String> returnTypes) {
this.httpMethod = httpMethod;
this.uri = uri;
this.sourceFile = sourceFile;
this.paramTypes = paramTypes == null ? Set.of() : new LinkedHashSet<>(paramTypes);
this.returnTypes = returnTypes == null ? Set.of() : new LinkedHashSet<>(returnTypes);
}
public String getHttpMethod() {
return httpMethod;
}
public String getUri() {
return uri;
}
/** 定义该接口的 Java 源文件相对路径 */
public String getSourceFile() {
return sourceFile;
}
/** 入参涉及的类型简单名集合 */
public Set<String> getParamTypes() {
return paramTypes;
}
/** 返回值涉及的类型简单名集合(已剥离泛型包装) */
public Set<String> getReturnTypes() {
return returnTypes;
}
/** 去重用键METHOD + URI */
public String endpointKey() {
return httpMethod + " " + uri;
}
/** 通知展示行GET /api/foo */
public String displayLine() {
return httpMethod + " " + uri;
}
}

View File

@@ -0,0 +1,67 @@
package com.codechecker.model;
/**
* Git 扫描得到的单个 Java 模型类变更记录。
*/
public class ChangedClassFile {
/** Git diff 状态:修改 / 删除 / 重命名 */
public enum ChangeStatus {
MODIFIED, DELETED, RENAMED
}
private final String relativePath;
private final String oldRelativePath;
private final ChangeStatus status;
private final String className;
private final String oldClassName;
private final ClassType classType;
/** 修改或删除(无路径变化) */
public ChangedClassFile(String relativePath, ChangeStatus status, String className, ClassType classType) {
this(relativePath, null, status, className, null, classType);
}
/** 重命名或同路径类名变更 */
public ChangedClassFile(String relativePath, String oldRelativePath, ChangeStatus status,
String className, String oldClassName, ClassType classType) {
this.relativePath = relativePath;
this.oldRelativePath = oldRelativePath;
this.status = status;
this.className = className;
this.oldClassName = oldClassName;
this.classType = classType;
}
/** 新提交中的相对路径 */
public String getRelativePath() {
return relativePath;
}
/** 旧提交中的相对路径,未变路径则为 null */
public String getOldRelativePath() {
return oldRelativePath;
}
/** 读取旧版本源码时使用的路径 */
public String pathForOldCommit() {
return oldRelativePath != null ? oldRelativePath : relativePath;
}
public ChangeStatus getStatus() {
return status;
}
/** 当前简单类名 */
public String getClassName() {
return className;
}
/** 重命名前简单类名 */
public String getOldClassName() {
return oldClassName;
}
public ClassType getClassType() {
return classType;
}
}

View File

@@ -0,0 +1,15 @@
package com.codechecker.model;
/**
* 单次类变更的类型,决定通知内容与影响分析策略。
*/
public enum ClassChangeKind {
/** 文件已删除 */
DELETED,
/** 仅字段变更 */
FIELDS_ONLY,
/** 仅类名变更,字段不变 */
RENAME_ONLY,
/** 类名与字段同时变更 */
RENAME_AND_FIELDS
}

View File

@@ -0,0 +1,126 @@
package com.codechecker.model;
import java.util.ArrayList;
import java.util.List;
/**
* 单次类变更的完整报告:变更类型、字段 diff、接口/转换影响,供通知渲染。
*/
public class ClassChangeReport {
private final String className;
private final String oldClassName;
private final ClassType classType;
private final ClassChangeKind changeKind;
private final String sourceFile;
private final String classDescription;
private final List<FieldChange> fieldChanges = new ArrayList<>();
private final List<ApiEndpoint> inputImpactEndpoints = new ArrayList<>();
private final List<String> conversionEntities = new ArrayList<>();
private final List<ApiEndpoint> frontendImpactEndpoints = new ArrayList<>();
private final boolean conversionCheckEnabled;
public ClassChangeReport(String className, String oldClassName, ClassType classType,
ClassChangeKind changeKind, String sourceFile,
boolean conversionCheckEnabled, String classDescription) {
this.className = className;
this.oldClassName = oldClassName;
this.classType = classType;
this.changeKind = changeKind;
this.sourceFile = sourceFile;
this.conversionCheckEnabled = conversionCheckEnabled;
this.classDescription = classDescription == null ? "" : classDescription.trim();
}
/** 当前(新)简单类名 */
public String getClassName() {
return className;
}
/** 重命名前的简单类名,未重命名则为 null */
public String getOldClassName() {
return oldClassName;
}
/** 是否发生类名变更 */
public boolean isRenamed() {
return oldClassName != null && !oldClassName.equals(className);
}
/** 是否仅类名变更、字段无变化 */
public boolean isRenameOnly() {
return changeKind == ClassChangeKind.RENAME_ONLY;
}
public ClassType getClassType() {
return classType;
}
public ClassChangeKind getChangeKind() {
return changeKind;
}
/** Git 相对路径,通知「文件路径」展示用 */
public String getSourceFile() {
return sourceFile;
}
/** 类级中文说明(@Schema / 类 Javadoc无则空串 */
public String getClassDescription() {
return classDescription;
}
/** 是否整文件删除 */
public boolean isDeleted() {
return changeKind == ClassChangeKind.DELETED;
}
public List<FieldChange> getFieldChanges() {
return fieldChanges;
}
/** 入参引用该类的接口request 影响) */
public List<ApiEndpoint> getInputImpactEndpoints() {
return inputImpactEndpoints;
}
/** Dto→Entity 转换目标类名列表 */
public List<String> getConversionEntities() {
return conversionEntities;
}
/** 返回值引用该类的接口response 影响) */
public List<ApiEndpoint> getFrontendImpactEndpoints() {
return frontendImpactEndpoints;
}
/** 是否启用类转换检测 */
public boolean isConversionCheckEnabled() {
return conversionCheckEnabled;
}
/** 追加一条字段变更 */
public void addFieldChange(FieldChange change) {
fieldChanges.add(change);
}
/** 追加 request 影响接口(按 endpointKey 去重) */
public void addInputImpact(ApiEndpoint endpoint) {
if (inputImpactEndpoints.stream().noneMatch(e -> e.endpointKey().equals(endpoint.endpointKey()))) {
inputImpactEndpoints.add(endpoint);
}
}
/** 追加关联 Entity 类名(去重) */
public void addConversionEntity(String entityName) {
if (!conversionEntities.contains(entityName)) {
conversionEntities.add(entityName);
}
}
/** 追加 response 影响接口(按 endpointKey 去重) */
public void addFrontendImpact(ApiEndpoint endpoint) {
if (frontendImpactEndpoints.stream().noneMatch(e -> e.endpointKey().equals(endpoint.endpointKey()))) {
frontendImpactEndpoints.add(endpoint);
}
}
}

View File

@@ -0,0 +1,47 @@
package com.codechecker.model;
/**
* 目标模型类后缀类型,决定通知模版中展示哪些影响段落。
*/
public enum ClassType {
DTO("Dto"),
VO("Vo"),
ENTITY("Entity"),
MODEL("Model");
private final String label;
ClassType(String label) {
this.label = label;
}
/** 通知中展示的类型标签 */
public String getLabel() {
return label;
}
/** 根据简单类名后缀识别类型,不匹配则 null */
public static ClassType fromClassName(String className) {
if (className.endsWith("Dto")) {
return DTO;
}
if (className.endsWith("VO")) {
return VO;
}
if (className.endsWith("Vo")) {
return VO;
}
if (className.endsWith("Entity")) {
return ENTITY;
}
if (className.endsWith("Model")) {
return MODEL;
}
return null;
}
/** 判断类名是否属于当前类型 */
public boolean isTargetSuffix(String className) {
return fromClassName(className) == this;
}
}

View File

@@ -0,0 +1,95 @@
package com.codechecker.model;
/**
* 字段级 diff 结果,用于通知中的 [新增]/[删除]/[修改]/[重命名] 行。
*/
public class FieldChange {
/** 字段变更种类 */
public enum ChangeKind {
ADDED, REMOVED, MODIFIED, RENAMED
}
private final ChangeKind kind;
private final String fieldName;
private final String oldFieldName;
private final String description;
private final String oldType;
private final String newType;
private final String oldDescription;
private final String detail;
private FieldChange(ChangeKind kind, String fieldName, String oldFieldName, String description,
String oldType, String newType, String oldDescription, String detail) {
this.kind = kind;
this.fieldName = fieldName;
this.oldFieldName = oldFieldName;
this.description = description;
this.oldType = oldType;
this.newType = newType;
this.oldDescription = oldDescription;
this.detail = detail;
}
/** 构造新增字段变更 */
public static FieldChange added(FieldInfo field) {
return new FieldChange(ChangeKind.ADDED, field.getName(), null, field.getDescription(),
null, field.getType(), null, null);
}
/** 构造删除字段变更 */
public static FieldChange removed(FieldInfo field) {
return new FieldChange(ChangeKind.REMOVED, field.getName(), null, field.getDescription(),
field.getType(), null, field.getDescription(), null);
}
/** 构造修改字段变更detail 通常为类型变化描述 */
public static FieldChange modified(FieldInfo oldField, FieldInfo newField, String detail) {
return new FieldChange(ChangeKind.MODIFIED, newField.getName(), null, newField.getDescription(),
oldField.getType(), newField.getType(), oldField.getDescription(), detail);
}
/** 构造字段重命名;类型变化时 detail 为 oldType → newType */
public static FieldChange renamed(FieldInfo oldField, FieldInfo newField) {
String typeDetail = oldField.getType().equals(newField.getType())
? null
: oldField.getType() + "" + newField.getType();
return new FieldChange(ChangeKind.RENAMED, newField.getName(), oldField.getName(),
newField.getDescription(), oldField.getType(), newField.getType(),
oldField.getDescription(), typeDetail);
}
public ChangeKind getKind() {
return kind;
}
public String getFieldName() {
return fieldName;
}
/** 重命名前的字段名,仅 RENAMED 时有值 */
public String getOldFieldName() {
return oldFieldName;
}
/** 变更后的字段说明(通知「说明」段) */
public String getDescription() {
return description;
}
public String getOldType() {
return oldType;
}
public String getNewType() {
return newType;
}
public String getOldDescription() {
return oldDescription;
}
/** 结构性变更详情,重命名时为类型变化描述 */
public String getDetail() {
return detail;
}
}

View File

@@ -0,0 +1,52 @@
package com.codechecker.model;
import java.util.Objects;
/**
* 解析后的单个字段名称、类型、业务说明Schema/注释)。
*/
public class FieldInfo {
private final String name;
private final String type;
private final String description;
public FieldInfo(String name, String type, String description) {
this.name = name;
this.type = type;
this.description = description == null ? "" : description;
}
/** 字段名 */
public String getName() {
return name;
}
/** 字段类型(简单名) */
public String getType() {
return type;
}
/** 字段说明文案 */
public String getDescription() {
return description;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof FieldInfo)) {
return false;
}
FieldInfo other = (FieldInfo) o;
return Objects.equals(name, other.name)
&& Objects.equals(type, other.type)
&& Objects.equals(description, other.description);
}
@Override
public int hashCode() {
return Objects.hash(name, type, description);
}
}