Code Linter 与代码质量 — 使用 code-linter.json5 保障工程规范
文章简介
在团队协作开发中,统一的代码风格和质量标准是保障工程可维护性的基石。HarmonyOS 提供了 Code Linter 工具,通过code-linter.json5配置文件定义代码风格和安全规则。MoneyTrack 项目配置了包括 @typescript-eslint 规则、安全规则和性能规则在内的完整 Linter 体系。本文从 Linter 在开发流程中的定位出发,详细解析配置语法、规则体系、命名规范以及 CI/CD 集成方案。
Linter 在开发流程中的位置
Code Linter 应嵌入到从编码到发布的整个流程中,形成自动化的质量门禁:
核心知识点
1. code-linter.json5 完整配置
code-linter.json5是 Code Linter 的核心配置文件,位于项目根目录下。MoneyTrack 项目的完整配置如下:
{ // 指定要扫描的文件匹配模式 "files": ["**/*.ets", "**/*.ts"], // 排除不需要扫描的目录 "ignore": [ "**/ohosTest/**/*", "**/test/**/*", "**/build/**/*", "**/oh_modules/**/*" ], // 启用规则集(plugin 前缀表示来自插件) "ruleSet": [ "plugin:@performance/recommended", "plugin:@typescript-eslint/recommended", "plugin:@hw-stylistic/recommended", "plugin:@security/recommended" ], // 细粒度规则配置(覆盖 ruleSet 中的默认行为) "rules": { // ===== 安全规则 ===== "@security/no-unsafe-aes": "error", "@security/no-hardcoded-credentials": "error", // ===== TypeScript 类型规则 ===== "@typescript-eslint/await-thenable": "error", "@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/explicit-member-accessibility": ["error", { "accessibility": "explicit", "overrides": { "constructors": "no-public" } }], "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/prefer-readonly": "warn", // ===== 命名规范 ===== "@typescript-eslint/naming-convention": ["error", { "selector": "default", "format": ["camelCase", "UPPER_CASE"] }, { "selector": "variable", "format": ["camelCase", "UPPER_CASE"] }, { "selector": "function", "format": ["camelCase"] }, { "selector": "class", "format": ["PascalCase"] }, { "selector": "interface", "format": ["PascalCase"] }, { "selector": "enum", "format": ["PascalCase"] }, { "selector": "enumMember", "format": ["UPPER_CASE"] }, { "selector": "memberLike", "modifiers": ["private"], "format": ["camelCase"], "leadingUnderscore": "require" }], // ===== 风格规则 ===== "@hw-stylistic/quotes": ["error", "single"], "@hw-stylistic/semi": ["error", "always"], "@hw-stylistic/comma-dangle": ["error", "always-multiline"], "@hw-stylistic/indent": ["error", 2], "@hw-stylistic/max-len": ["warn", { "code": 120 }], // ===== 变量声明规则 ===== "init-declarations": ["error", "always"] } }配置字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
files | string[] | 文件匹配模式,决定哪些文件被扫描 |
ignore | string[] | 排除模式,跳过不需要检查的目录 |
ruleSet | string[] | 引用的预定义规则集,支持plugin:前缀 |
rules | object | 单个规则的启用/禁用/配置,值可为"off"、"warn"、"error"或配置数组 |
2. @typescript-eslint 常用规则详解
| 规则名 | 级别 | 作用 | 违反示例 | 正确示例 |
|---|---|---|---|---|
await-thenable | error | 禁止 await 非 Promise 值 | await someString | await somePromise |
no-floating-promises | error | 禁止未处理的 Promise | asyncFunc() | await asyncFunc() |
explicit-member-accessibility | error | 要求显式成员访问修饰符 | name: string | public name: string |
consistent-type-definitions | error | 强制使用 interface | type User = { id: number } | interface User { id: number } |
prefer-readonly | warn | 建议只读成员加 readonly | private id: number | private readonly id: number |
naming-convention | error | 强制统一命名规范 | class user_service | class UserService |
no-unused-vars | error | 禁止声明未使用的变量 | const x = 1(未使用) | 删除或使用_x前缀 |
prefer-optional-chain | warn | 建议使用可选链 | a && a.b | a?.b |
3. 命名规范完整要求
MoneyTrack 项目遵循以下命名规范,由naming-convention规则强制执行:
| 代码元素 | 规范 | 示例 | 说明 |
|---|---|---|---|
| 变量(普通) | camelCase | userName、billList、totalAmount | 普通变量统一小驼峰 |
| 变量(常量) | UPPER_CASE | MAX_RETRY_COUNT、API_BASE_URL | 全局常量全大写+下划线 |
| 函数/方法 | camelCase | initData()、refreshBill()、getTotalIncome() | 动宾结构,小驼峰 |
| 类 | PascalCase | HomeVM、StatisticsVM、BillRepository | 名词或名词短语 |
| 接口 | PascalCase | IBill、IUserInfo、PageState | 可以是I前缀或无前缀 |
| 枚举 | PascalCase | BillType、Category、TransactionStatus | 名词形式 |
| 枚举成员 | UPPER_CASE | EXPENSE、INCOME、PENDING、COMPLETED | 全大写+下划线 |
| 私有成员 | camelCase +_前缀 | _instance、_cacheData、_subscription | 下划线开头表示私有 |
| 类型参数 | PascalCase 单字母 | T、K、V、R | 泛型统一单大写字母 |
项目中的实际应用:
// ✅ 符合规范constMAX_PAGE_SIZE:number=50;letuserName:string='';classHomeVM{privatereadonly_instance:HomeVM;private_billList:Bill[]=[];publicasyncinitData():Promise<void>{// 初始化逻辑}publicgetTotalIncome():number{returnthis._billList.reduce((sum,bill)=>sum+bill.amount,0);}}interfaceIBill{id:string;amount:number;category:Category;}enumCategory{FOOD='FOOD',TRANSPORT='TRANSPORT',ENTERTAINMENT='ENTERTAINMENT',}// ❌ 违反规范classhome_vm{}// 类必须 PascalCasefunctionGet_Data(){}// 函数必须 camelCaseletUser_Name='test';// 变量必须 camelCaseconstmax_count=10;// 常量必须 UPPER_CASE4. CI/CD 集成
Pre-commit Hook 配置:
在.husky/pre-commit中配置提交前自动运行 Linter:
#!/bin/sh."$(dirname"$0")/_/husky.sh"# 对暂存的文件运行 Linternpx code-linter--files="$(gitdiff--cached--name-only --diff-filter=d|grep-E'\.(ets|ts)$'|tr'\n'',')"if[$?-ne0];thenecho"❌ Lint 检查未通过,请修复后重新提交"exit1fiCI 流水线集成(oh-pipeline.json5):
{ "stages": [{ "name": "quality-gate", "jobs": [{ "name": "code-lint", "steps": [ { "name": "安装依赖", "command": "ohpm install" }, { "name": "运行 Linter", "command": "code-linter --config code-linter.json5" }, { "name": "运行单元测试", "command": "ohos test --build-type local" } ] }] }] }最佳实践
渐进式启用:不要一次性开启所有规则。先启用核心规则(如命名规范、安全规则),等团队适应后再逐步增加风格类规则,避免大量报错打乱开发节奏。
规则覆盖优先级:
rules中的单个规则配置优先级高于ruleSet中的默认配置。在ruleSet基础上通过rules微调,而不需要删除整个规则集。Lint 即文档:将命名规范、代码风格等约定通过 Linter 规则强制执行,而不是写在团队规范文档中。这样新的团队成员不需要记忆大量规则,Linter 会实时提示。
CI 门禁:在 CI 流水线中设置 Lint 检查为门禁卡点,Lint 未通过的代码不能合并到主分支。这比依赖开发人员自觉性更可靠。
阶段区分:在本地开发和 pre-commit 阶段只对变更文件进行检查(速度快),在 CI 阶段对全量文件扫描(确保全面),两者配合使用。
定期审查:每个迭代结束后审查 Linter 报错统计,如果某些规则频繁被违反,考虑是否规则过于严格或不合理,及时调整配置。
推荐参考文档
- HarmonyOS Code Linter 工具文档
- @typescript-eslint 规则参考
- code-linter.json5 配置语法
- 代码审查最佳实践指南