# Java 编码规范 Gate 规则
# 来源: 华为Java语言编程规范V5.4.pdf + 华为云计算最小规则集（Java）.xlsx

rules:
  # === 命名规范 (G.NAM) ===

  - id: java-identifier-length
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.01"
    message: "标识符长度不应超过64字符"
    pattern: "\\b\\w{65,}\\b"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-package-lowercase
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.02"
    message: "包名必须全部小写，以点号分隔层级"
    pattern: "package\\s+[^;]*[A-Z]"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-class-naming
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.03"
    message: "类、枚举和接口名必须使用PascalCase"
    pattern: "^(class|enum|interface)\\s+[a-z]"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-method-naming
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.04"
    message: "方法名必须使用camelCase"
    pattern: "\\bpublic\\s+\\w+\\s+[A-Z][a-z]"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-constant-naming
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.05"
    message: "常量必须使用UPPER_SNAKE_CASE"
    pattern: "\\bfinal\\s+static\\s+(?!\\w+_)[a-z]"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-boolean-negative-name
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.NAM.07"
    message: "避免使用具有否定含义的布尔变量名（如isNotReady）"
    pattern: "\\b(isNot|isNot[A-Z]|not[A-Z])\\w*\\b"
    match_mode: absent
    includes:
      - "**/*.java"

  # === 注释规范 (G.CMT) ===

  - id: java-javadoc-public
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CMT.01"
    message: "public或protected修饰的元素应添加Javadoc注释"
    pattern: "/\\*\\*\\s*\\n.*@param|@return|@throws"
    match_mode: present
    includes:
      - "**/*.java"

  - id: java-no-todo-in-prod
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CMT.07"
    message: "正式交付代码不应包含TODO/FIXME注释"
    pattern: "(TODO|FIXME)"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  # === 格式规范 (G.FMT) ===

  - id: java-no-tab-indent
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.FMT.08"
    message: "禁止使用制表符缩进，使用4个空格"
    pattern: "\t"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-trailing-whitespace
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.FMT.12"
    message: "删除行尾多余空格"
    pattern: " +$"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-brace-style
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.FMT.06"
    message: "左大括号须与代码同一行"
    pattern: "^\\s*\\)\\s*\\{\\s*\\n\\s*\\w"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-max-line-length
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.FMT.10"
    message: "单行代码建议不超过120字符"
    pattern: ".{121,}$"
    match_mode: present
    includes:
      - "**/*.java"

  # === 声明和初始化规范 (G.DCL) ===

  - id: java-no-c-array-declaration
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.DCL.03"
    message: "禁止C风格的数组声明（int arr[]）"
    pattern: "\\b\\w+\\s+\\w+\\[\\]"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-mutable-public-static-final
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.DCL.05"
    message: "禁止将mutable对象声明为public static final"
    pattern: "public\\s+static\\s+final\\s+(List|Map|Set|StringBuffer|StringBuilder)\\s+\\w+"
    match_mode: absent
    includes:
      - "**/*.java"

  # === 数据类型规范 (G.TYP) ===

  - id: java-use-bigdecimal
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.TYP.04"
    message: "需要精确计算时使用BigDecimal，不要使用float和double"
    pattern: "(float|double)\\s+\\w+\\s*=\\s*\\d+\\.\\d+"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-no-float-comparison
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.TYP.05"
    message: "浮点型数据判断相等不要直接使用==或equals()"
    pattern: "(==\\s*\\d+\\.\\d+|\\.equals\\s*\\(\\s*\\d+\\.\\d+)"
    match_mode: absent
    includes:
      - "**/*.java"

  # === 表达式规范 (G.EXP) ===

  - id: java-no-assign-in-condition
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.EXP.01"
    message: "不要在条件表达式中执行赋值操作"
    pattern: "\\((\\s*\\w+\\s*=)"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-assert
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.EXP.06"
    message: "代码中不应使用断言（assert）"
    pattern: "\\bassert\\s+"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  # === 控制语句规范 (G.CTL) ===

  - id: java-switch-default
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CTL.03"
    message: "switch语句必须有default分支"
    pattern: "switch\\s*\\([^)]+\\)\\s*\\{[^}]*\\}"
    match_mode: present
    includes:
      - "**/*.java"

  - id: java-no-nested-switch
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CTL.06"
    message: "禁止switch语句中直接嵌套switch"
    pattern: "switch\\s*\\([^)]+\\)\\s*\\{[^}]*switch\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"

  # === 方法规范 (G.MET) ===

  - id: java-no-deprecated-method
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.MET.02"
    message: "不要使用已标注为@Deprecated的方法"
    pattern: "@Deprecated"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-use-optional
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.MET.06"
    message: "使用Optional代替null作为返回值"
    pattern: "return\\s+null;"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  # === 类和接口规范 (G.OBJ) ===

  - id: java-no-public-non-final-field
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.OBJ.01"
    message: "避免定义public且非final的类属性"
    pattern: "public\\s+(?!final\\s)\\w+\\s+\\w+"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-override-annotation
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.OBJ.07"
    message: "覆写父类方法或实现接口时必须加上@Override注解"
    pattern: "(?<!@Override\\s+)\\b(public|protected|private)\\s+\\w+\\s+\\w+\\([^)]*\\)"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-equals-hashcode
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.OBJ.06"
    message: "覆写equals方法时必须同时覆写hashCode方法"
    pattern: "public\\s+boolean\\s+equals\\(Object\\s+o\\)"
    match_mode: present
    includes:
      - "**/*.java"

  # === 异常处理规范 (G.ERR) ===

  - id: java-no-empty-catch
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.ERR.01"
    message: "不要通过空catch块忽略异常"
    pattern: "catch\\s*\\([^)]+\\)\\s*\\{\\s*\\}"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-bare-catch
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.ERR.02"
    message: "不要直接捕获异常的基类Throwable、Exception、RuntimeException"
    pattern: "catch\\s*\\(\\s*(Throwable|Exception|RuntimeException)\\s+\\w+\\s*\\)"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-catch-npe
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.ERR.03"
    message: "不要直接捕获NullPointerException，应通过预检查处理"
    pattern: "catch\\s*\\(\\s*NullPointerException\\s+\\w+\\s*\\)"
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-system-exit
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.ERR.09"
    message: "不要调用System.exit()终止JVM"
    pattern: "System\\.exit\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"
      - "**/Main.java"

  # === 并发与多线程规范 (G.CON) ===

  - id: java-thread-name
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CON.07"
    message: "创建新线程时必须指定线程名"
    pattern: "new\\s+Thread\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-no-thread-stop
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CON.11"
    message: "禁止使用Thread.stop()终止线程"
    pattern: "Thread\\.stop\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-use-threadpool
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.CON.12"
    message: "避免不加控制地创建新线程，使用线程池"
    pattern: "new\\s+Thread\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  # === 泛型和集合规范 (G.COL) ===

  - id: java-no-modify-in-foreach
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.COL.04"
    message: "不要在foreach循环中通过remove()/add()方法更改集合"
    pattern: "for\\s*\\([^:]+:\\s+[^)]+\\)\\s*\\{[^}]*\\.(remove|add)\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"

  # === 输入输出规范 (G.FIO) ===

  - id: java-use-try-with-resources
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-G.FIO.03"
    message: "IO流须使用try-with-resources自动关闭"
    pattern: "new\\s+(FileInputStream|FileOutputStream|BufferedReader|BufferedWriter).*[^;{]$"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"

  # === 日志规范 ===

  - id: java-no-sout-in-prod
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-日志"
    message: "禁止使用System.out/err，使用日志框架"
    pattern: "System\\.(out|err)\\."
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-no-printstacktrace
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为云计算Java规则-AvoidPrintStackTrace"
    message: "禁止使用printStackTrace()，防止信息泄露"
    pattern: "\\.printStackTrace\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  # === 安全规范 ===

  - id: java-no-hardcoded-credential
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-安全"
    message: "禁止硬编码凭据，使用环境变量或配置文件"
    pattern: "(password|secret|apiKey|token)\\s*=\\s*['\"][^'\"]{8,}"
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-sql-injection
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为Java规范-安全"
    message: "使用参数化查询，禁止字符串拼接SQL"
    pattern: "\"\\s*\\+\\s*.*\\.execute\\(|Statement\\.execute\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"
    excludes:
      - "**/test*.java"
      - "**/*Test.java"

  - id: java-no-throw-npe
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为云计算Java规则-AvoidThrowingNullPointerException"
    message: "避免手动抛出NullPointerException，使用Objects.requireNonNull()"
    pattern: "throw\\s+new\\s+NullPointerException\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"

  - id: java-no-call-finalize
    type: regex-check
    blocking: false
    severity: warning
    scope: incremental
    source: "华为云计算Java规则-AvoidCallingFinalize"
    message: "不要调用Object.finalize()方法，JDK 9已废弃"
    pattern: "\\.finalize\\s*\\("
    match_mode: absent
    includes:
      - "**/*.java"