mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-07-09 17:28:58 +00:00
feat(rules): extract inline rule content into separate markdown files
Move verbose rule definitions from system_rules.json into individual markdown files under rule_docs/, loaded at runtime via embed.FS. This improves maintainability by separating rule content from config structure and merges duplicate mapper/dao XML patterns into one entry.
This commit is contained in:
parent
ce73f388d1
commit
971ab0a626
16 changed files with 457 additions and 29 deletions
1
internal/config/rules/rule_docs/build_gradle.md
Normal file
1
internal/config/rules/rule_docs/build_gradle.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
避免引入snapshot版本的依赖发布线上环境,建议引入具体的版本号。注意:版本号并非新增的代码行时请忽略。
|
||||
61
internal/config/rules/rule_docs/c.md
Normal file
61
internal/config/rules/rule_docs/c.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#### 明确的错别字或拼写错误识别
|
||||
- 定义处的变量名、常量名、函数名中包含拼写错误,请不要报告调用处的拼写错误
|
||||
- 日志或异常信息中的字符串包含影响阅读理解的拼写错误
|
||||
|
||||
#### malloc/free配对使用
|
||||
**检查要点:**
|
||||
- 每个`malloc()`都有对应的`free()`
|
||||
- 避免重复释放同一内存块
|
||||
- 释放后将指针设为NULL
|
||||
|
||||
**示例:**
|
||||
```c
|
||||
// ❌ 错误示例
|
||||
char* buffer = malloc(1024);
|
||||
// 使用buffer...
|
||||
// 忘记释放内存
|
||||
|
||||
// ✅ 正确示例
|
||||
char* buffer = malloc(1024);
|
||||
if (buffer != NULL) {
|
||||
// 使用buffer...
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
```
|
||||
|
||||
#### 内存泄漏检查
|
||||
**检查要点:**
|
||||
- 所有分配的内存在函数退出前都被释放
|
||||
- 错误处理路径中也要释放内存
|
||||
- 使用工具如Valgrind进行检测
|
||||
|
||||
#### 缓冲区溢出防护
|
||||
**检查要点:**
|
||||
- 数组访问前检查边界
|
||||
- 字符串操作使用安全函数
|
||||
- 循环边界条件正确
|
||||
|
||||
**示例:**
|
||||
```c
|
||||
// ❌ 危险操作
|
||||
char buffer[100];
|
||||
strcpy(buffer, user_input); // 可能溢出
|
||||
|
||||
// ✅ 安全操作
|
||||
char buffer[100];
|
||||
strncpy(buffer, user_input, sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
```
|
||||
|
||||
#### 字符串操作安全
|
||||
**推荐使用的安全函数:**
|
||||
- `strncpy()` 替代 `strcpy()`
|
||||
- `strncat()` 替代 `strcat()`
|
||||
- `snprintf()` 替代 `sprintf()`
|
||||
|
||||
#### 命名规范
|
||||
**要求:**
|
||||
- 使用snake_case命名方式
|
||||
- 变量名要有意义
|
||||
- 常量使用UPPER_CASE
|
||||
71
internal/config/rules/rule_docs/cpp.md
Normal file
71
internal/config/rules/rule_docs/cpp.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#### 明确的错别字或拼写错误识别
|
||||
- 定义处的变量名、常量名、函数名中包含拼写错误,请不要报告调用处的拼写错误
|
||||
- 日志或异常信息中的字符串包含影响阅读理解的拼写错误
|
||||
|
||||
#### 死代码
|
||||
- 永远不会被执行到的代码块(如条件恒为 false 的分支、return 语句后的代码)
|
||||
- 声明后从未被读取或引用的变
|
||||
- 已注释掉的大段代码块(无明显保留意图的注释代码)
|
||||
|
||||
#### 智能指针使用
|
||||
**检查要点:**
|
||||
- 优先使用`std::unique_ptr`管理独占资源
|
||||
- 使用`std::shared_ptr`管理共享资源
|
||||
- 避免使用裸指针管理动态内存
|
||||
- 正确使用`std::weak_ptr`打破循环引用
|
||||
|
||||
**示例:**
|
||||
```cpp
|
||||
// ❌ 避免使用裸指针
|
||||
Widget* widget = new Widget();
|
||||
delete widget; // 容易忘记或异常时不执行
|
||||
|
||||
// ✅ 使用智能指针
|
||||
auto widget = std::make_unique<Widget>();
|
||||
// 自动析构,异常安全
|
||||
```
|
||||
|
||||
#### RAII原则
|
||||
**检查要点:**
|
||||
- 资源在构造函数中获取
|
||||
- 资源在析构函数中释放
|
||||
- 使用栈对象管理资源
|
||||
- 避免手动资源管理
|
||||
|
||||
#### STL容器和算法
|
||||
**检查要点:**
|
||||
- 优先使用STL容器而非数组
|
||||
- 使用STL算法而非手写循环
|
||||
- 选择合适的容器类型
|
||||
- 了解容器的性能特征
|
||||
|
||||
**示例:**
|
||||
```cpp
|
||||
// ❌ 手写循环
|
||||
std::vector<int> vec = {1, 2, 3, 4, 5};
|
||||
for (int i = 0; i < vec.size(); ++i) {
|
||||
vec[i] *= 2;
|
||||
}
|
||||
|
||||
// ✅ 使用算法
|
||||
std::transform(vec.begin(), vec.end(), vec.begin(),
|
||||
[](int x) { return x * 2; });
|
||||
```
|
||||
|
||||
#### auto关键字
|
||||
**检查要点:**
|
||||
- 类型复杂时使用auto
|
||||
- 避免在简单类型上滥用auto
|
||||
- 使用auto&和const auto&避免拷贝
|
||||
|
||||
#### 异常处理完整性
|
||||
**检查要点:**
|
||||
- 捕获具体异常类型而非...
|
||||
- 异常处理不要忽略错误
|
||||
|
||||
#### const正确性
|
||||
**检查要点:**
|
||||
- 成员函数const修饰
|
||||
- 参数const引用传递
|
||||
- 指针和引用的const位置
|
||||
- const成员变量合理使用
|
||||
18
internal/config/rules/rule_docs/default.md
Normal file
18
internal/config/rules/rule_docs/default.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#### Correctness
|
||||
Is the logic correct? Are there missing boundary conditions?
|
||||
Are exceptions handled properly?
|
||||
Is it thread-safe in concurrent scenarios?
|
||||
#### Security
|
||||
Are there security vulnerabilities such as SQL injection or XSS?
|
||||
Is sensitive information handled correctly?
|
||||
Is permission validation complete?
|
||||
#### Performance
|
||||
Are there obvious performance issues (e.g., N+1 queries, unnecessary loops)?
|
||||
Are resources properly released?
|
||||
#### Maintainability
|
||||
Is the code clear and easy to understand?
|
||||
Do names accurately express intent?
|
||||
Does it follow the project’s existing code style and architecture patterns?
|
||||
#### Test Coverage
|
||||
Do critical logic paths have corresponding test cases?
|
||||
Do test cases cover boundary conditions?
|
||||
41
internal/config/rules/rule_docs/java.md
Normal file
41
internal/config/rules/rule_docs/java.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#### 明确的错别字或拼写错误
|
||||
- 定义处的变量名、方法名、类名中的拼写错误(通过`code.search`搜索同类命名规范确认)
|
||||
- 日志或异常信息中的字符串包含影响阅读理解的拼写错误
|
||||
- 请不要报告引用处的拼写错误,因为这些通常是由定义决定的
|
||||
|
||||
#### 死代码
|
||||
- 永远不会被执行到的代码块(如条件恒为 false 的分支、return 语句后的代码)
|
||||
- 声明后从未被读取或引用的变
|
||||
- 已注释掉的大段代码块(无明显保留意图的注释代码)
|
||||
|
||||
#### 逻辑错误识别
|
||||
- if 条件逻辑错误(使用`file.read`查看上下文确认预期逻辑)
|
||||
- 边界条件处理错误(特别关注索引、数组长度判断等)
|
||||
- 布尔逻辑运算符误用(优先级、短路评估问题)
|
||||
- 明显的死循环或递归中无终止条件
|
||||
- 在不应该退出的地方使用 return/break/continue
|
||||
- switch case 缺少 break 语句导致的意外穿透
|
||||
- 有意的穿透但缺少注释说明
|
||||
- 可能导致NPE的代码模式(通过`file.read`和`code.search`检查数据来源调用链确认风险)
|
||||
- 逻辑表达式缺少括号导致执行顺序可能与预期不一致
|
||||
|
||||
#### 严重性能隐患
|
||||
- 在循环内部执行数据库查询(通过`code.search`确认方法调用是否涉及数据库操作)
|
||||
- N+1查询问题(应建议批量查询优化)
|
||||
- 未分页的大数据集处理(可通过`file.read`了解数据规模和处理上下文)
|
||||
- 嵌套循环中的低效算法实现(O(n²)及以上复杂度但有更优解法)
|
||||
|
||||
#### 线程安全问题识别
|
||||
仅在以下情况下才指出线程安全问题:
|
||||
- **竞态条件**:存在"检查-然后-执行"模式,中间状态可能被其他线程改变
|
||||
- **复合操作原子性缺失**:多步操作需要保证原子性但未使用同步机制
|
||||
- **不安全的懒加载**:单例模式或缓存实现中的双重检查锁定缺陷
|
||||
- **线程不安全集合的并发写操作**:多线程环境下对ArrayList、HashMap等非线程安全集合的修改
|
||||
|
||||
以下情况下不应报告:
|
||||
- **方法内部的局部变量**:这些天然线程安全,每个线程都有独立副本
|
||||
- **单线程上下文的使用**:未发现明显的多线程调用(可通过`code.search`搜索相关调用上下文确认)
|
||||
- **只读操作**:即使使用非线程安全的数据结构,如果只进行读取操作
|
||||
- **不可变对象**:final字段且指向不可变对象的引用
|
||||
- **已有适当同步机制**:代码已使用synchronized、Lock、原子类等正确同步
|
||||
- **设计为单线程使用的组件**:如Builder模式的构建过程、临时数据传输对象等
|
||||
1
internal/config/rules/rule_docs/json.md
Normal file
1
internal/config/rules/rule_docs/json.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
检查JSON文件中的json-key是否存在拼写错误,忽略json-value的内容。
|
||||
134
internal/config/rules/rule_docs/kotlin.md
Normal file
134
internal/config/rules/rule_docs/kotlin.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
### 1. 空安全(Null Safety)
|
||||
- **问题**:未正确处理可空类型,导致潜在的`NullPointerException`。
|
||||
- **检查点**:
|
||||
- 避免滥用`!!`(非空断言),优先使用安全调用`?.`或Elvis操作符`?:`。
|
||||
- 数据类或API返回的可空属性是否合理处理。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
val length: Int = text!!.length // 风险:text可能为null
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
val length: Int = text?.length ?: 0 // 安全处理
|
||||
```
|
||||
|
||||
#### 死代码
|
||||
- 永远不会被执行到的代码块(如条件恒为 false 的分支、return 语句后的代码)
|
||||
- 声明后从未被读取或引用的变
|
||||
- 已注释掉的大段代码块(无明显保留意图的注释代码)
|
||||
|
||||
### 2. 函数与表达式简洁性
|
||||
- **问题**:冗余代码破坏Kotlin的简洁性。
|
||||
- **检查点**:
|
||||
- 单表达式函数是否用`=`简化(如`fun sum(a: Int, b: Int) = a + b`)。
|
||||
- 是否用`when`替代复杂`if-else`链。
|
||||
- 避免不必要的`return`(如Lambda中直接使用表达式结果)。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
fun getGrade(score: Int): String {
|
||||
if (score >= 90) return "A"
|
||||
else if (score >= 80) return "B"
|
||||
else return "C"
|
||||
}
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
fun getGrade(score: Int) = when {
|
||||
score >= 90 -> "A"
|
||||
score >= 80 -> "B"
|
||||
else -> "C"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 集合操作优化
|
||||
- **问题**:低效的集合操作导致性能问题。
|
||||
- **检查点**:
|
||||
- 优先使用`Sequence`处理大型集合(惰性求值减少中间对象)。
|
||||
- 避免重复操作(如多次`filter`合并为一次)。
|
||||
- 使用`groupBy`、`associate`等替代手动迭代。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
val evenSquares = listOf(1, 2, 3).map { it * it }.filter { it % 2 == 0 } // 产生中间集合
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
val evenSquares = listOf(1, 2, 3).asSequence()
|
||||
.map { it * it }
|
||||
.filter { it % 2 == 0 }
|
||||
.toList() // 惰性计算
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 协程(Coroutines)正确使用
|
||||
- **问题**:协程泄漏或异常处理不当。
|
||||
- **检查点**:
|
||||
- 使用结构化并发(`coroutineScope`或`supervisorScope`管理生命周期)。
|
||||
- 避免`GlobalScope`(易导致资源泄漏)。
|
||||
- 异常处理:用`try/catch`包裹`withContext`或`async`。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
GlobalScope.launch { // 脱离作用域,可能泄漏
|
||||
fetchData()
|
||||
}
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
viewModelScope.launch { // 结构化并发
|
||||
try {
|
||||
withContext(Dispatchers.IO) { fetchData() }
|
||||
} catch (e: Exception) { /* 处理异常 */ }
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 类与对象设计
|
||||
- **问题**:未合理使用Kotlin特性导致冗余。
|
||||
- **检查点**:
|
||||
- **数据类**:纯数据对象用`data class`(自动生成`equals`/`hashCode`)。
|
||||
- **密封类/接口**:受限类型层次用`sealed class`(完善`when`分支检查)。
|
||||
- **委托**:属性委托(如`by lazy`)或类委托(`by`实现装饰器模式)。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
class User(val name: String) {
|
||||
// 手动实现toString()/equals()...
|
||||
}
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
data class User(val name: String) // 自动生成标准方法
|
||||
```
|
||||
|
||||
### 6. 资源管理与作用域函数
|
||||
- **问题**:资源未释放或作用域函数滥用。
|
||||
- **检查点**:
|
||||
- 文件/网络资源用`use`自动关闭(如`FileInputStream().use { ... }`)。
|
||||
- 作用域函数(`let`、`apply`等)需保持可读性,避免嵌套过深。
|
||||
- **坏例子**:
|
||||
```kotlin
|
||||
val file = File("path")
|
||||
val reader = BufferedReader(FileReader(file))
|
||||
// 忘记调用reader.close()
|
||||
```
|
||||
- **改进**:
|
||||
```kotlin
|
||||
File("path").inputStream().use { stream ->
|
||||
// 自动关闭资源
|
||||
}
|
||||
```
|
||||
|
||||
### 7. 性能陷阱
|
||||
- **问题**:隐藏的性能开销。
|
||||
- **检查点**:
|
||||
- 内联函数:高阶函数用`inline`减少Lambda开销(但避免对大函数内联)。
|
||||
- 常量:编译时常量用`const val`(取代`val`)。
|
||||
- 避免在循环中创建对象(如正则表达式`Regex`)。
|
||||
|
||||
### 8. 互操作性(Java交互)
|
||||
- **问题**:Java调用Kotlin代码时的兼容性问题。
|
||||
- **检查点**:
|
||||
- 暴露API时用`@JvmStatic`、`@JvmOverloads`优化Java调用。
|
||||
- 空安全注解:`@Nullable`/`@NonNull`辅助Java识别可空性。
|
||||
|
||||
### 9. 其他关键点
|
||||
- **不可变性**:优先使用`val`而非`var`。
|
||||
- **字符串处理**:用字符串模板(`"Value: $value"`)替代拼接。
|
||||
33
internal/config/rules/rule_docs/mapper_dao_xml.md
Normal file
33
internal/config/rules/rule_docs/mapper_dao_xml.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#### 明确拼写错误识别
|
||||
- SQL关键字的拼写错误
|
||||
- mapper接口方法名与XML中id不匹配的拼写错误
|
||||
- 动态SQL标签中的属性名拼写错误(如 `test` 条件中的字段名)
|
||||
|
||||
#### SQL逻辑错误识别
|
||||
- **条件判断错误**:WHERE条件中的逻辑运算符误用(AND/OR混淆)
|
||||
- **JOIN条件错误**:关联条件使用错误的字段或缺少必要的关联条件
|
||||
- **动态SQL逻辑错误**:`<if test="">` 条件判断错误,如空值判断、类型判断错误
|
||||
- **SQL语法错误**:明显的语法错误,如缺少逗号、括号不匹配
|
||||
|
||||
#### 严重的性能问题
|
||||
- **全表扫描风险**:WHERE条件缺失
|
||||
- **大数据量查询缺少分页**:可能返回大量数据但未使用LIMIT或分页机制
|
||||
- **重复子查询**:同一个子查询在多处使用,建议提取为临时表或优化SQL结构
|
||||
|
||||
#### SQL注入安全风险识别
|
||||
|
||||
**应该报告的真实安全风险:**
|
||||
- **直接字符串拼接**:使用`${}`拼接用户输入的参数到SQL语句中,存在SQL注入风险
|
||||
- **LIKE查询拼接**:直接拼接LIKE条件而非使用安全的参数绑定方式
|
||||
|
||||
**不应该报告的情况:**
|
||||
- **正确使用 #{} 参数绑定**:MyBatis会自动进行参数转义,安全性有保障
|
||||
- **静态SQL语句**:不涉及动态参数的固定SQL语句
|
||||
|
||||
**审查原则:**
|
||||
- 重点关注可能导致数据错误、性能问题或安全风险的严重问题
|
||||
- 考虑SQL语句的实际执行效率和数据库性能影响
|
||||
- 优先识别可能导致生产环境故障的关键问题
|
||||
- 上下文不明时保持谨慎:当无法确定SQL执行的完整上下文时,应选择忽略而不是误报
|
||||
- 需要充分证据:只有在有明确证据表明存在问题时才进行报告
|
||||
- 宁可漏报不要误报:保持高精度的问题识别,避免因过多误报而干扰对真实问题的关注
|
||||
3
internal/config/rules/rule_docs/package_json.md
Normal file
3
internal/config/rules/rule_docs/package_json.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
- 避免引入版本为 latest 或 *,建议引入具体的版本号。注意:版本号并非新增的代码行时请忽略
|
||||
- 依赖冲突或重复声明:同一依赖同时存在于 dependencies 和 devDependencies
|
||||
- 必需工具依赖未声明:scripts 里出现如 eslint、jest、prettier 等工具名称但未在 devDependencies 中体现
|
||||
1
internal/config/rules/rule_docs/pom_xml.md
Normal file
1
internal/config/rules/rule_docs/pom_xml.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
新增的代码中,version不允许包含snapshot字段,只允许引入其他的任何版本。注意:代码中没有声明版本号是因为版本号在父pom中管理,当版本号并非新增的代码行时请忽略。
|
||||
10
internal/config/rules/rule_docs/properties.md
Normal file
10
internal/config/rules/rule_docs/properties.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#### 明确的错别字或拼写错误识别
|
||||
- 键名中的拼写错误,特别是常用配置项的标准拼写
|
||||
|
||||
#### 配置错误识别
|
||||
- 当前文件中存在可见范围内重复的键定义导致配置覆盖问题
|
||||
- 键值对格式错误(缺少等号、多余空格等)
|
||||
- 特殊字符未正确转义(如路径中的反斜杠、Unicode字符等)
|
||||
|
||||
#### 严重的安全问题
|
||||
- 敏感信息(密码、API密钥、数据库连接串等)以明文形式存储
|
||||
40
internal/config/rules/rule_docs/ts_js_tsx_jsx.md
Normal file
40
internal/config/rules/rule_docs/ts_js_tsx_jsx.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#### 明确的错别字或拼写错误识别
|
||||
- 变量名、函数名、组件名、Props 属性名中的拼写错误
|
||||
- 日志或错误信息中的字符串包含影响阅读理解的拼写错误
|
||||
|
||||
#### 死代码
|
||||
- 永远不会被执行到的代码块(如条件恒为 false 的分支、return 语句后的代码)
|
||||
- 声明后从未被读取或引用的变
|
||||
- 已注释掉的大段代码块(无明显保留意图的注释代码)
|
||||
|
||||
#### 代码质量检查
|
||||
- **重复代码**:检查是否有可以抽取的公共逻辑
|
||||
- **代码注释**:复杂业务逻辑是否有清晰的注释说明(避免显而易见的代码注释)
|
||||
- **硬编码检查**:禁止使用业务相关的硬编码字符串,特别是 URL 路径、业务数字;简单 UI 文本可适当放宽
|
||||
- **变量声明**:严格禁止使用 var,必须使用 let 或 const
|
||||
- **相等比较**:禁止使用==和!=,必须使用严格相等===和!==
|
||||
- **TypeScript 类型**:避免使用 any 类型,如需使用请注释说明原因
|
||||
- **空值判断**:在取值或解构赋值时进行空值判断,避免空指针异常
|
||||
- **三元表达式**:不允许嵌套三元表达式
|
||||
|
||||
#### React 最佳实践
|
||||
- **Hooks 使用**:是否遵循 Hooks 规则(只在顶层调用、只在 React 函数中调用)
|
||||
- **状态管理**:状态是否放在合适的层级,避免不必要的状态提升
|
||||
- **副作用处理**:useEffect 是否正确处理依赖和清理函数
|
||||
- **性能优化**:是否合理使用 React.memo、useMemo、useCallback(基于性能分析,避免过度优化)
|
||||
- **render 副作用**:严格禁止在 React 组件的 render 方法中进行副作用操作(如 API 调用、DOM 操作
|
||||
- **内联样式**:避免使用内联 style 样式,动态样式除外
|
||||
- **内部组件**:禁止在组件内部声明一个新组件,如有需要请使用方法的方式来渲染,如`renderItem` ,而不是`<Item/>`
|
||||
|
||||
#### 异步处理规范
|
||||
- **错误处理**:异步函数必须包含适当的错误处理,并提供用户友好的错误提示
|
||||
- **async/await 优先**:相较于 Promise 更推荐使用 async/await,禁止使用回调地狱
|
||||
- **循环异步**:区分独立异步操作(用 Promise.all 并行)和依赖性异步操作(用串行),优先考虑 Promise.all 来提升性能
|
||||
|
||||
#### 代码安全性检查
|
||||
- **XSS 防护**:是否对用户输入进行适当的转义
|
||||
- **innerHTML 安全**:禁止使用 innerHTML 直接插入用户输入内容,必须使用 textContent 或进行 XSS 防护
|
||||
- **代码注入防护**:严格禁止使用 eval()、Function()构造函数和 setTimeout/setInterval 的字符串参数形式
|
||||
- **危险方法**:禁止使用 document.write(),会导致页面重绘和安全问题
|
||||
- **敏感信息**:是否暴露了 API 密钥或敏感数据
|
||||
- **原型链安全**:禁止修改原生对象的原型链(如 Array.prototype、Object.prototype
|
||||
1
internal/config/rules/rule_docs/yaml.md
Normal file
1
internal/config/rules/rule_docs/yaml.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
检查YAML文件中的yaml-key是否存在拼写错误,忽略yaml-value的内容。
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
package rules
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
|
@ -80,15 +80,31 @@ func (r *SystemRule) UnmarshalJSON(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
//go:embed system_rules.json
|
||||
var defaultSystemRules []byte
|
||||
//go:embed system_rules.json rule_docs/*
|
||||
var rulesFS embed.FS
|
||||
|
||||
// LoadDefault parses the embedded system_rules.json.
|
||||
// LoadDefault parses the embedded system_rules.json and resolves rule file references.
|
||||
func LoadDefault() (*SystemRule, error) {
|
||||
data, err := rulesFS.ReadFile("system_rules.json")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read embedded system_rules.json: %w", err)
|
||||
}
|
||||
var rule SystemRule
|
||||
if err := json.Unmarshal(defaultSystemRules, &rule); err != nil {
|
||||
if err := json.Unmarshal(data, &rule); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal default system rules: %w", err)
|
||||
}
|
||||
content, err := rulesFS.ReadFile("rule_docs/" + rule.DefaultRule)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read default rule file %q: %w", rule.DefaultRule, err)
|
||||
}
|
||||
rule.DefaultRule = strings.TrimRight(string(content), "\n")
|
||||
for i := range rule.PathRules {
|
||||
content, err := rulesFS.ReadFile("rule_docs/" + rule.PathRules[i].Rule)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read rule file %q for pattern %q: %w", rule.PathRules[i].Rule, rule.PathRules[i].Pattern, err)
|
||||
}
|
||||
rule.PathRules[i].Rule = strings.TrimRight(string(content), "\n")
|
||||
}
|
||||
return &rule, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
{
|
||||
"default_rule": "新增的代码存在明确的错别字或拼写错误。",
|
||||
"default_rule": "default.md",
|
||||
"path_rule_map": {
|
||||
"**/*.properties": "#### 明确的错别字或拼写错误识别\n- 键名中的拼写错误,特别是常用配置项的标准拼写\n\n#### 配置错误识别\n- 当前文件中存在可见范围内重复的键定义导致配置覆盖问题\n- 键值对格式错误(缺少等号、多余空格等)\n- 特殊字符未正确转义(如路径中的反斜杠、Unicode字符等)\n\n#### 严重的安全问题\n- 敏感信息(密码、API密钥、数据库连接串等)以明文形式存储",
|
||||
"**/*mapper*.xml": "#### 明确拼写错误识别\n- SQL关键字的拼写错误\n- mapper接口方法名与XML中id不匹配的拼写错误\n- 动态SQL标签中的属性名拼写错误(如 `test` 条件中的字段名)\n\n#### SQL逻辑错误识别\n- **条件判断错误**:WHERE条件中的逻辑运算符误用(AND/OR混淆)\n- **JOIN条件错误**:关联条件使用错误的字段或缺少必要的关联条件\n- **动态SQL逻辑错误**:`<if test=\"\">` 条件判断错误,如空值判断、类型判断错误\n- **SQL语法错误**:明显的语法错误,如缺少逗号、括号不匹配\n\n#### 严重的性能问题\n- **全表扫描风险**:WHERE条件缺失\n- **大数据量查询缺少分页**:可能返回大量数据但未使用LIMIT或分页机制\n- **重复子查询**:同一个子查询在多处使用,建议提取为临时表或优化SQL结构\n\n#### SQL注入安全风险识别\n\n**应该报告的真实安全风险:**\n- **直接字符串拼接**:使用`${}`拼接用户输入的参数到SQL语句中,存在SQL注入风险\n- **LIKE查询拼接**:直接拼接LIKE条件而非使用安全的参数绑定方式\n\n**不应该报告的情况:**\n- **正确使用 #{} 参数绑定**:MyBatis会自动进行参数转义,安全性有保障\n- **静态SQL语句**:不涉及动态参数的固定SQL语句\n\n**审查原则:**\n- 重点关注可能导致数据错误、性能问题或安全风险的严重问题\n- 考虑SQL语句的实际执行效率和数据库性能影响\n- 优先识别可能导致生产环境故障的关键问题\n- 上下文不明时保持谨慎:当无法确定SQL执行的完整上下文时,应选择忽略而不是误报\n- 需要充分证据:只有在有明确证据表明存在问题时才进行报告\n- 宁可漏报不要误报:保持高精度的问题识别,避免因过多误报而干扰对真实问题的关注",
|
||||
"**/*dao*.xml": "#### 明确拼写错误识别\n- SQL关键字的拼写错误\n- mapper接口方法名与XML中id不匹配的拼写错误\n- 动态SQL标签中的属性名拼写错误(如 `test` 条件中的字段名)\n\n#### SQL逻辑错误识别\n- **条件判断错误**:WHERE条件中的逻辑运算符误用(AND/OR混淆)\n- **JOIN条件错误**:关联条件使用错误的字段或缺少必要的关联条件\n- **动态SQL逻辑错误**:`<if test=\"\">` 条件判断错误,如空值判断、类型判断错误\n- **SQL语法错误**:明显的语法错误,如缺少逗号、括号不匹配\n\n#### 严重的性能问题\n- **全表扫描风险**:WHERE条件缺失\n- **大数据量查询缺少分页**:可能返回大量数据但未使用LIMIT或分页机制\n- **重复子查询**:同一个子查询在多处使用,建议提取为临时表或优化SQL结构\n\n#### SQL注入安全风险识别\n\n**应该报告的真实安全风险:**\n- **直接字符串拼接**:使用`${}`拼接用户输入的参数到SQL语句中,存在SQL注入风险\n- **LIKE查询拼接**:直接拼接LIKE条件而非使用安全的参数绑定方式\n\n**不应该报告的情况:**\n- **正确使用 #{} 参数绑定**:MyBatis会自动进行参数转义,安全性有保障\n- **静态SQL语句**:不涉及动态参数的固定SQL语句\n\n**审查原则:**\n- 重点关注可能导致数据错误、性能问题或安全风险的严重问题\n- 考虑SQL语句的实际执行效率和数据库性能影响\n- 优先识别可能导致生产环境故障的关键问题\n- 上下文不明时保持谨慎:当无法确定SQL执行的完整上下文时,应选择忽略而不是误报\n- 需要充分证据:只有在有明确证据表明存在问题时才进行报告\n- 宁可漏报不要误报:保持高精度的问题识别,避免因过多误报而干扰对真实问题的关注",
|
||||
"**/pom.xml": "新增的代码中,version不允许包含snapshot字段,只允许引入其他的任何版本。注意:代码中没有声明版本号是因为版本号在父pom中管理,当版本号并非新增的代码行时请忽略。",
|
||||
"**/build.gradle": "避免引入snapshot版本的依赖发布线上环境,建议引入具体的版本号。注意:版本号并非新增的代码行时请忽略。",
|
||||
"**/package.json": "- 避免引入版本为 latest 或 *,建议引入具体的版本号。注意:版本号并非新增的代码行时请忽略\n- 依赖冲突或重复声明:同一依赖同时存在于 dependencies 和 devDependencies\n- 必需工具依赖未声明:scripts 里出现如 eslint、jest、prettier 等工具名称但未在 devDependencies 中体现",
|
||||
"**/*.json": "检查JSON文件中的json-key是否存在拼写错误,忽略json-value的内容。",
|
||||
"**/*.{yaml,yml}": "检查YAML文件中的yaml-key是否存在拼写错误,忽略yaml-value的内容。",
|
||||
"**/*.java": "#### 明确的错别字或拼写错误\n- 定义处的变量名、方法名、类名中的拼写错误(通过`code.search`搜索同类命名规范确认)\n- 日志或异常信息中的字符串包含影响阅读理解的拼写错误\n- 请不要报告引用处的拼写错误,因为这些通常是由定义决定的\n\n#### 逻辑错误识别\n- if 条件逻辑错误(使用`file.read`查看上下文确认预期逻辑)\n- 边界条件处理错误(特别关注索引、数组长度判断等)\n- 布尔逻辑运算符误用(优先级、短路评估问题)\n- 明显的死循环或递归中无终止条件\n- 在不应该退出的地方使用 return/break/continue\n- switch case 缺少 break 语句导致的意外穿透\n- 有意的穿透但缺少注释说明\n- 可能导致NPE的代码模式(通过`file.read`和`code.search`检查数据来源调用链确认风险)\n- 逻辑表达式缺少括号导致执行顺序可能与预期不一致\n\n#### 严重性能隐患\n- 在循环内部执行数据库查询(通过`code.search`确认方法调用是否涉及数据库操作)\n- N+1查询问题(应建议批量查询优化)\n- 未分页的大数据集处理(可通过`file.read`了解数据规模和处理上下文)\n- 嵌套循环中的低效算法实现(O(n²)及以上复杂度但有更优解法)\n\n#### 线程安全问题识别\n仅在以下情况下才指出线程安全问题:\n- **竞态条件**:存在\"检查-然后-执行\"模式,中间状态可能被其他线程改变\n- **复合操作原子性缺失**:多步操作需要保证原子性但未使用同步机制\n- **不安全的懒加载**:单例模式或缓存实现中的双重检查锁定缺陷\n- **线程不安全集合的并发写操作**:多线程环境下对ArrayList、HashMap等非线程安全集合的修改\n\n以下情况下不应报告:\n- **方法内部的局部变量**:这些天然线程安全,每个线程都有独立副本\n- **单线程上下文的使用**:未发现明显的多线程调用(可通过`code.search`搜索相关调用上下文确认)\n- **只读操作**:即使使用非线程安全的数据结构,如果只进行读取操作\n- **不可变对象**:final字段且指向不可变对象的引用\n- **已有适当同步机制**:代码已使用synchronized、Lock、原子类等正确同步\n- **设计为单线程使用的组件**:如Builder模式的构建过程、临时数据传输对象等",
|
||||
"**/*.{ts,js,tsx,jsx}": "#### 明确的错别字或拼写错误识别\n- 变量名、函数名、组件名、Props 属性名中的拼写错误\n- 日志或错误信息中的字符串包含影响阅读理解的拼写错误\n\n#### 代码质量检查\n- **重复代码**:检查是否有可以抽取的公共逻辑\n- **代码注释**:复杂业务逻辑是否有清晰的注释说明(避免显而易见的代码注释)\n- **硬编码检查**:禁止使用业务相关的硬编码字符串,特别是 URL 路径、业务数字;简单 UI 文本可适当放宽\n- **变量声明**:严格禁止使用 var,必须使用 let 或 const\n- **相等比较**:禁止使用==和!=,必须使用严格相等===和!==\n- **TypeScript 类型**:避免使用 any 类型,如需使用请注释说明原因\n- **空值判断**:在取值或解构赋值时进行空值判断,避免空指针异常\n- **三元表达式**:不允许嵌套三元表达式\n \n#### React 最佳实践\n- **Hooks 使用**:是否遵循 Hooks 规则(只在顶层调用、只在 React 函数中调用)\n- **状态管理**:状态是否放在合适的层级,避免不必要的状态提升\n- **副作用处理**:useEffect 是否正确处理依赖和清理函数\n- **性能优化**:是否合理使用 React.memo、useMemo、useCallback(基于性能分析,避免过度优化)\n- **render 副作用**:严格禁止在 React 组件的 render 方法中进行副作用操作(如 API 调用、DOM 操作\n- **内联样式**:避免使用内联 style 样式,动态样式除外\n- **内部组件**:禁止在组件内部声明一个新组件,如有需要请使用方法的方式来渲染,如`renderItem` ,而不是`<Item/>`\n \n#### 异步处理规范\n- **错误处理**:异步函数必须包含适当的错误处理,并提供用户友好的错误提示\n- **async/await 优先**:相较于 Promise 更推荐使用 async/await,禁止使用回调地狱\n- **循环异步**:区分独立异步操作(用 Promise.all 并行)和依赖性异步操作(用串行),优先考虑 Promise.all 来提升性能\n \n#### 代码安全性检查\n- **XSS 防护**:是否对用户输入进行适当的转义\n- **innerHTML 安全**:禁止使用 innerHTML 直接插入用户输入内容,必须使用 textContent 或进行 XSS 防护\n- **代码注入防护**:严格禁止使用 eval()、Function()构造函数和 setTimeout/setInterval 的字符串参数形式\n- **危险方法**:禁止使用 document.write(),会导致页面重绘和安全问题\n- **敏感信息**:是否暴露了 API 密钥或敏感数据\n- **原型链安全**:禁止修改原生对象的原型链(如 Array.prototype、Object.prototype",
|
||||
"**/*.{kt}": "### 1. 空安全(Null Safety)\n- **问题**:未正确处理可空类型,导致潜在的`NullPointerException`。\n- **检查点**:\n - 避免滥用`!!`(非空断言),优先使用安全调用`?.`或Elvis操作符`?:`。\n - 数据类或API返回的可空属性是否合理处理。\n- **坏例子**:\n ```kotlin\n val length: Int = text!!.length // 风险:text可能为null\n ```\n- **改进**:\n ```kotlin\n val length: Int = text?.length ?: 0 // 安全处理\n ```\n\n### 2. 函数与表达式简洁性\n- **问题**:冗余代码破坏Kotlin的简洁性。\n- **检查点**:\n - 单表达式函数是否用`=`简化(如`fun sum(a: Int, b: Int) = a + b`)。\n - 是否用`when`替代复杂`if-else`链。\n - 避免不必要的`return`(如Lambda中直接使用表达式结果)。\n- **坏例子**:\n ```kotlin\n fun getGrade(score: Int): String {\n if (score >= 90) return \"A\"\n else if (score >= 80) return \"B\"\n else return \"C\"\n }\n ```\n- **改进**:\n ```kotlin\n fun getGrade(score: Int) = when {\n score >= 90 -> \"A\"\n score >= 80 -> \"B\"\n else -> \"C\"\n }\n ```\n\n### 3. 集合操作优化\n- **问题**:低效的集合操作导致性能问题。\n- **检查点**:\n - 优先使用`Sequence`处理大型集合(惰性求值减少中间对象)。\n - 避免重复操作(如多次`filter`合并为一次)。\n - 使用`groupBy`、`associate`等替代手动迭代。\n- **坏例子**:\n ```kotlin\n val evenSquares = listOf(1, 2, 3).map { it * it }.filter { it % 2 == 0 } // 产生中间集合\n ```\n- **改进**:\n ```kotlin\n val evenSquares = listOf(1, 2, 3).asSequence()\n .map { it * it }\n .filter { it % 2 == 0 }\n .toList() // 惰性计算\n ```\n\n---\n\n### 4. 协程(Coroutines)正确使用\n- **问题**:协程泄漏或异常处理不当。\n- **检查点**:\n - 使用结构化并发(`coroutineScope`或`supervisorScope`管理生命周期)。\n - 避免`GlobalScope`(易导致资源泄漏)。\n - 异常处理:用`try/catch`包裹`withContext`或`async`。\n- **坏例子**:\n ```kotlin\n GlobalScope.launch { // 脱离作用域,可能泄漏\n fetchData()\n }\n ```\n- **改进**:\n ```kotlin\n viewModelScope.launch { // 结构化并发\n try {\n withContext(Dispatchers.IO) { fetchData() }\n } catch (e: Exception) { /* 处理异常 */ }\n }\n ```\n\n### 5. 类与对象设计\n- **问题**:未合理使用Kotlin特性导致冗余。\n- **检查点**:\n - **数据类**:纯数据对象用`data class`(自动生成`equals`/`hashCode`)。\n - **密封类/接口**:受限类型层次用`sealed class`(完善`when`分支检查)。\n - **委托**:属性委托(如`by lazy`)或类委托(`by`实现装饰器模式)。\n- **坏例子**:\n ```kotlin\n class User(val name: String) {\n // 手动实现toString()/equals()...\n }\n ```\n- **改进**:\n ```kotlin\n data class User(val name: String) // 自动生成标准方法\n ```\n\n### 6. 资源管理与作用域函数\n- **问题**:资源未释放或作用域函数滥用。\n- **检查点**:\n - 文件/网络资源用`use`自动关闭(如`FileInputStream().use { ... }`)。\n - 作用域函数(`let`、`apply`等)需保持可读性,避免嵌套过深。\n- **坏例子**:\n ```kotlin\n val file = File(\"path\")\n val reader = BufferedReader(FileReader(file))\n // 忘记调用reader.close()\n ```\n- **改进**:\n ```kotlin\n File(\"path\").inputStream().use { stream ->\n // 自动关闭资源\n }\n ```\n\n### 7. 性能陷阱\n- **问题**:隐藏的性能开销。\n- **检查点**:\n - 内联函数:高阶函数用`inline`减少Lambda开销(但避免对大函数内联)。\n - 常量:编译时常量用`const val`(取代`val`)。\n - 避免在循环中创建对象(如正则表达式`Regex`)。\n\n### 8. 互操作性(Java交互)\n- **问题**:Java调用Kotlin代码时的兼容性问题。\n- **检查点**:\n - 暴露API时用`@JvmStatic`、`@JvmOverloads`优化Java调用。\n - 空安全注解:`@Nullable`/`@NonNull`辅助Java识别可空性。\n\n### 9. 其他关键点\n- **不可变性**:优先使用`val`而非`var`。\n- **字符串处理**:用字符串模板(`\"Value: $value\"`)替代拼接。",
|
||||
"**/*.{go,py,ets,lua,dart,swift,groovy}": "1.新增的代码存在严重的逻辑问题。比如if中的条件写反了,bool类型变量赋值了相反的值,错误的使用了依赖库的接口,或者逻辑表达式缺少括号导致执行顺序跟预期不一致等。\n2.新增的代码存在明确的错别字或拼写错误。",
|
||||
"**/*.{h,m,mm}": "1.新增的代码存在严重的逻辑问题。比如if中的条件写反了,bool类型变量赋值了相反的值,错误的使用了依赖库的接口,或者逻辑表达式缺少括号导致执行顺序跟预期不一致等。\n2.新增的代码存在明确的错别字或拼写错误。\n3.新增的代码中存在确定的数组越界问题,由于上下文不足无法确认数组会越界时请忽略。",
|
||||
"**/*.{cpp,cc,hpp}": "#### 明确的错别字或拼写错误识别\n- 定义处的变量名、常量名、函数名中包含拼写错误,请不要报告调用处的拼写错误\n- 日志或异常信息中的字符串包含影响阅读理解的拼写错误\n\n#### 智能指针使用\n**检查要点:**\n- 优先使用`std::unique_ptr`管理独占资源\n- 使用`std::shared_ptr`管理共享资源\n- 避免使用裸指针管理动态内存\n- 正确使用`std::weak_ptr`打破循环引用\n\n**示例:**\n```cpp\n// ❌ 避免使用裸指针\nWidget* widget = new Widget();\ndelete widget; // 容易忘记或异常时不执行\n\n// ✅ 使用智能指针\nauto widget = std::make_unique<Widget>();\n// 自动析构,异常安全\n```\n\n#### RAII原则\n**检查要点:**\n- 资源在构造函数中获取\n- 资源在析构函数中释放\n- 使用栈对象管理资源\n- 避免手动资源管理\n\n#### STL容器和算法\n**检查要点:**\n- 优先使用STL容器而非数组\n- 使用STL算法而非手写循环\n- 选择合适的容器类型\n- 了解容器的性能特征\n\n**示例:**\n```cpp\n// ❌ 手写循环\nstd::vector<int> vec = {1, 2, 3, 4, 5};\nfor (int i = 0; i < vec.size(); ++i) {\n vec[i] *= 2;\n}\n\n// ✅ 使用算法\nstd::transform(vec.begin(), vec.end(), vec.begin(),\n [](int x) { return x * 2; });\n```\n\n#### auto关键字\n**检查要点:**\n- 类型复杂时使用auto\n- 避免在简单类型上滥用auto\n- 使用auto&和const auto&避免拷贝\n\n#### 异常处理完整性\n**检查要点:**\n- 捕获具体异常类型而非...\n- 异常处理不要忽略错误\n\n#### const正确性\n**检查要点:**\n- 成员函数const修饰\n- 参数const引用传递\n- 指针和引用的const位置\n- const成员变量合理使用",
|
||||
"**/*.c": "#### 明确的错别字或拼写错误识别\n- 定义处的变量名、常量名、函数名中包含拼写错误,请不要报告调用处的拼写错误\n- 日志或异常信息中的字符串包含影响阅读理解的拼写错误\n\n#### malloc/free配对使用\n**检查要点:**\n- 每个`malloc()`都有对应的`free()`\n- 避免重复释放同一内存块\n- 释放后将指针设为NULL\n\n**示例:**\n```c\n// ❌ 错误示例\nchar* buffer = malloc(1024);\n// 使用buffer...\n// 忘记释放内存\n\n// ✅ 正确示例\nchar* buffer = malloc(1024);\nif (buffer != NULL) {\n // 使用buffer...\n free(buffer);\n buffer = NULL;\n}\n```\n\n#### 内存泄漏检查\n**检查要点:**\n- 所有分配的内存在函数退出前都被释放\n- 错误处理路径中也要释放内存\n- 使用工具如Valgrind进行检测\n\n#### 缓冲区溢出防护\n**检查要点:**\n- 数组访问前检查边界\n- 字符串操作使用安全函数\n- 循环边界条件正确\n\n**示例:**\n```c\n// ❌ 危险操作\nchar buffer[100];\nstrcpy(buffer, user_input); // 可能溢出\n\n// ✅ 安全操作\nchar buffer[100];\nstrncpy(buffer, user_input, sizeof(buffer) - 1);\nbuffer[sizeof(buffer) - 1] = '\\0';\n```\n\n#### 字符串操作安全\n**推荐使用的安全函数:**\n- `strncpy()` 替代 `strcpy()`\n- `strncat()` 替代 `strcat()`\n- `snprintf()` 替代 `sprintf()`\n\n#### 命名规范\n**要求:**\n- 使用snake_case命名方式\n- 变量名要有意义\n- 常量使用UPPER_CASE"
|
||||
"**/*.properties": "properties.md",
|
||||
"**/*{mapper,dao}*.xml": "mapper_dao_xml.md",
|
||||
"**/pom.xml": "pom_xml.md",
|
||||
"**/build.gradle": "build_gradle.md",
|
||||
"**/package.json": "package_json.md",
|
||||
"**/*.json": "json.md",
|
||||
"**/*.{yaml,yml}": "yaml.md",
|
||||
"**/*.java": "java.md",
|
||||
"**/*.{ts,js,tsx,jsx}": "ts_js_tsx_jsx.md",
|
||||
"**/*.{kt}": "kotlin.md",
|
||||
"**/*.{cpp,cc,hpp}": "cpp.md",
|
||||
"**/*.c": "c.md"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ func TestResolve_DefaultRules(t *testing.T) {
|
|||
}{
|
||||
{"src/main/java/com/example/foo.java", "逻辑错误识别"},
|
||||
{"foo.java", "逻辑错误识别"},
|
||||
{"internal/agent/agent.go", "逻辑问题"},
|
||||
{"scripts/deploy.py", "逻辑问题"},
|
||||
{"src/main/resources/mapper/usermapper.xml", "SQL逻辑错误识别"},
|
||||
{"src/main/resources/dao/userdao.xml", "SQL逻辑错误识别"},
|
||||
{"pom.xml", "snapshot"},
|
||||
|
|
@ -74,7 +72,6 @@ func TestResolve_DefaultRules(t *testing.T) {
|
|||
{"app.kt", "空安全"},
|
||||
{"src/main/handler.cpp", "智能指针"},
|
||||
{"driver.c", "malloc"},
|
||||
{"ios/ViewController.m", "数组越界"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
@ -99,6 +96,9 @@ func TestResolve_FallbackToDefault(t *testing.T) {
|
|||
"docs/architecture.txt",
|
||||
"Makefile",
|
||||
"src/unknown.rs",
|
||||
"internal/agent/agent.go",
|
||||
"scripts/deploy.py",
|
||||
"ios/ViewController.m",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
|
|
@ -249,8 +249,8 @@ func TestNewResolver_ProjectRuleFallsBackToSystem(t *testing.T) {
|
|||
}
|
||||
|
||||
got := resolver.Resolve("other/main.go")
|
||||
if !strings.Contains(got, "逻辑问题") {
|
||||
t.Errorf("expected system go rule, got %q", truncate(got, 80))
|
||||
if !strings.Contains(got, "Correctness") {
|
||||
t.Errorf("expected system default rule, got %q", truncate(got, 80))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +273,7 @@ func TestNewResolver_CustomRuleOverridesDefault(t *testing.T) {
|
|||
}
|
||||
// --rule not matched → falls through to system default
|
||||
got = resolver.Resolve("readme.md")
|
||||
if !strings.Contains(got, "错别字") {
|
||||
if !strings.Contains(got, "Correctness") {
|
||||
t.Errorf("expected system default rule, got %q", truncate(got, 80))
|
||||
}
|
||||
}
|
||||
|
|
@ -310,7 +310,7 @@ func TestNewResolver_CustomOverridesProject(t *testing.T) {
|
|||
{"force-api/src/foo.java", "custom-java-rule"}, // --rule wins (highest priority)
|
||||
{"other/src/bar.java", "custom-java-rule"}, // --rule wins
|
||||
{"main.go", "project-go-rule"}, // --rule misses → project wins
|
||||
{"readme.md", "错别字"}, // all miss → system default
|
||||
{"readme.md", "Correctness"}, // all miss → system default
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.path, func(t *testing.T) {
|
||||
|
|
@ -543,7 +543,7 @@ func TestNewResolver_BraceExpansionInProjectRule(t *testing.T) {
|
|||
}{
|
||||
{"src/main/foo.java", "jvm-rule"},
|
||||
{"src/main/bar.kt", "jvm-rule"},
|
||||
{"src/main/baz.go", "逻辑问题"},
|
||||
{"src/main/baz.go", "Correctness"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.path, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue