Code Linter 与代码质量 — 使用 code-linter.json5 保障工程规范

在这里插入图片描述

文章简介

在团队协作开发中,统一的代码风格和质量标准是保障工程可维护性的基石。HarmonyOS 提供了 Code Linter 工具,通过 code-linter.json5 配置文件定义代码风格和安全规则。MoneyTrack 项目配置了包括 @typescript-eslint 规则、安全规则和性能规则在内的完整 Linter 体系。本文从 Linter 在开发流程中的定位出发,详细解析配置语法、规则体系、命名规范以及 CI/CD 集成方案。

Linter 在开发流程中的位置

Code Linter 应嵌入到从编码到发布的整个流程中,形成自动化的质量门禁:

编码阶段

本地 Lint 检查

是否通过

代码提交

Pre-commit Hook

再次通过

推送到远程

CI 流水线

全量 Lint 扫描

质量问题

代码合并

自动部署

核心知识点

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 userNamebillListtotalAmount 普通变量统一小驼峰
变量(常量) UPPER_CASE MAX_RETRY_COUNTAPI_BASE_URL 全局常量全大写+下划线
函数/方法 camelCase initData()refreshBill()getTotalIncome() 动宾结构,小驼峰
PascalCase HomeVMStatisticsVMBillRepository 名词或名词短语
接口 PascalCase IBillIUserInfoPageState 可以是 I 前缀或无前缀
枚举 PascalCase BillTypeCategoryTransactionStatus 名词形式
枚举成员 UPPER_CASE EXPENSEINCOMEPENDINGCOMPLETED 全大写+下划线
私有成员 camelCase + _ 前缀 _instance_cacheData_subscription 下划线开头表示私有
类型参数 PascalCase 单字母 TKVR 泛型统一单大写字母

项目中的实际应用:

// ✅ 符合规范
const MAX_PAGE_SIZE: number = 50;
let userName: string = '';

class HomeVM {
  private readonly _instance: HomeVM;
  private _billList: Bill[] = [];

  public async initData(): Promise<void> {
    // 初始化逻辑
  }

  public getTotalIncome(): number {
    return this._billList.reduce((sum, bill) => sum + bill.amount, 0);
  }
}

interface IBill {
  id: string;
  amount: number;
  category: Category;
}

enum Category {
  FOOD = 'FOOD',
  TRANSPORT = 'TRANSPORT',
  ENTERTAINMENT = 'ENTERTAINMENT',
}

// ❌ 违反规范
class home_vm {}           // 类必须 PascalCase
function Get_Data() {}     // 函数必须 camelCase
let User_Name = 'test';    // 变量必须 camelCase
const max_count = 10;      // 常量必须 UPPER_CASE

4. CI/CD 集成

Pre-commit Hook 配置:

.husky/pre-commit 中配置提交前自动运行 Linter:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# 对暂存的文件运行 Linter
npx code-linter --files="$(git diff --cached --name-only --diff-filter=d | grep -E '\.(ets|ts)$' | tr '\n' ',')"
if [ $? -ne 0 ]; then
  echo "❌ Lint 检查未通过,请修复后重新提交"
  exit 1
fi

CI 流水线集成(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" }
      ]
    }]
  }]
}

最佳实践

  1. 渐进式启用:不要一次性开启所有规则。先启用核心规则(如命名规范、安全规则),等团队适应后再逐步增加风格类规则,避免大量报错打乱开发节奏。

  2. 规则覆盖优先级rules 中的单个规则配置优先级高于 ruleSet 中的默认配置。在 ruleSet 基础上通过 rules 微调,而不需要删除整个规则集。

  3. Lint 即文档:将命名规范、代码风格等约定通过 Linter 规则强制执行,而不是写在团队规范文档中。这样新的团队成员不需要记忆大量规则,Linter 会实时提示。

  4. CI 门禁:在 CI 流水线中设置 Lint 检查为门禁卡点,Lint 未通过的代码不能合并到主分支。这比依赖开发人员自觉性更可靠。

  5. 阶段区分:在本地开发和 pre-commit 阶段只对变更文件进行检查(速度快),在 CI 阶段对全量文件扫描(确保全面),两者配合使用。

  6. 定期审查:每个迭代结束后审查 Linter 报错统计,如果某些规则频繁被违反,考虑是否规则过于严格或不合理,及时调整配置。

推荐参考文档

  • HarmonyOS Code Linter 工具文档
  • @typescript-eslint 规则参考
  • code-linter.json5 配置语法
  • 代码审查最佳实践指南
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐