csr 检查屏蔽错误

// csr-ignore 注释屏蔽校验错误 —— 使用说明

在开发 CSR 规则、编写 .sr 测试样例或示例文件时,常会遇到误报暂时不想修复的校验错误。CSR 文件是 JSONC 语法,支持 // 行注释,因此可以用 // csr-ignore 系列注释就地屏蔽错误,类似 mypy 的 # type: ignore、ESLint 的 // eslint-disable-line

屏蔽只影响"该文件被校验时"的诊断输出,不修改你的真实配置;注释留在代码里,评审时可见、可追溯,也方便在 RuleTester 用例里临时放行尚未实现的规则。

本机制由校验引擎(openubmc-meridarc)统一实现,规则 SDK 本身无需做任何适配:你编写的规则产出的诊断会自动受到这些注释约束。


一、四种指令速查

指令 作用 示例
// csr-ignore 屏蔽该行所有错误 "Address": "x", // csr-ignore
// csr-ignore: <code> 只屏蔽该行中 code 匹配的错误(逗号分隔多个) // csr-ignore: type,enum
// csr-ignore-next-line 屏蔽下一行(可带 : code // csr-ignore-next-line: type
// csr-ignore-file 屏蔽整个文件(可带 : code,写在文件顶部) // csr-ignore-file

裸指令(不带 code)按位置屏蔽该行/该文件的全部错误;带 code 的指令做精确匹配,只屏蔽对应那一类。


二、基础示例

以一个真实的网卡 .sr 文件片段为例。

1. 屏蔽整行的某个误报(裸指令)

Anchor.Buses 里引用 I2c_2,但拓扑里有个看着像笔误的 I2c_2qq,某条规则报了"未引用/命名不匹配",暂时不想动它:

"ManagementTopology": {
    "Anchor": {
        "Buses": ["I2c_2", "I2cMux_pca9545_chan1"]
    },
    "I2c_2qq": {              // csr-ignore
        "Chips": ["Smc_ExpBoardSMC"]
    }
}

这一行的错误全部消失,文件其余校验不受影响。

2. 只屏蔽某一类错误(带 code)

Eeprom_NIC.Address 用了表达式,但 schema 期望它是数字而报 type 错误。这一行如果还有别的错误想保留,就用 code 精确屏蔽:

"Eeprom_NIC": {
    "Address": "${Slot} |> expr($1 == 1 ? 160 : 164)",   // csr-ignore: type
    "AddrWidth": 1
}

3. 按规则 id 屏蔽规则错误

某条规则(比如 csr-004-anchor-bus-type-name)报了错,只想放行它:

"I2cMux_pca9545_chan1",   // csr-ignore: csr-004-anchor-bus-type-name

你自己用 @openubmc/csr-devkit 编写的规则,其 code 即 meta.id。因此在样例文件里按规则 id 屏蔽,对内置规则和外部规则用法完全一致。

4. 多行对象用"下一行"屏蔽

@Default / @Parent 这类微语法 key 偶尔被严格 schema 当成额外字段。值是多行对象时,把注释写在上一行更顺手:

// csr-ignore-next-line
"Event_OverTemp": {
    "@Default": { "Condition": 105 }
}

5. 整个文件临时不校验

文件顶部加一行(类似 TypeScript 的 // @ts-nocheck):

// csr-ignore-file
{
    "FormatVersion": "3.00",
    ...
}

三、复杂场景:规则错误 + Schema 错误混存

实际文件里,一个对象往往同时触发语义规则(跨对象引用、表达式正确性等)和 Schema 类型两类错误。它们的 code 来源不同,屏蔽方式也不同:

  • Schema 错误 → code 是 AJV 关键字(type / enum / required / additionalProperties …)。
  • 规则错误 → code 是规则 id(即规则的 meta.id,如 csr-015-parent-object-existscsr-020-sync-target-object-existscsr-027-string-function-correctness)。

下面这段是一个对象同时踩了两类错误、分别精确屏蔽的例子:

"NetworkPort_0": {
    "@Parent": "NetworkAdapter_1",   // 规则 csr-015 报:父对象不存在
    "SystemID": "should-be-number",  // schema 报:type 不匹配(应为整数)
    "MediumType": "Fiber",           // schema 报:enum 不在允许值里
    "Position": "<=/PCIeDevice_1.Position |> string.format('%s',$1)"  // 规则 csr-027 报:表达式参数不匹配
}

逐行精确屏蔽(每行只放行该行对应的那一类错误,互不影响):

"NetworkPort_0": {
    "@Parent": "NetworkAdapter_1",  // csr-ignore: csr-015-parent-object-exists  放行父对象引用规则
    "SystemID": "should-be-number", // csr-ignore: type                          放行类型错误
    "MediumType": "Fiber",          // csr-ignore: enum                          放行枚举错误
    "Position": "<=/PCIeDevice_1.Position |> string.format('%s',$1)"
                                    // csr-ignore: csr-027-string-function-correctness  放行表达式规则
}

也可以一条指令屏蔽多个 code(逗号分隔,混合关键字和规则 id 都行):

"Position": "<=/PCIeDevice_1.Position |> string.format('%s',$1)"
// csr-ignore: type,csr-027-string-function-correctness,additionalProperties

关键区别:规则 id 屏蔽的是"规则名"那一类(无论它在哪一行触发);关键字屏蔽的是"schema 校验类型"那一类。在 openubmc-meridarc 的诊断输出(或 RuleTester 的用例断言)里查看每条错误的 code 字段,就能确定该填哪个。

若懒得逐个查 code,对单行误报直接用裸 // csr-ignore(屏蔽该行全部)最省事;但要保留同行其它错误时,务必用带 code 的精确形式。


四、怎么知道该填哪个 code?

  1. Schema(类型)错误 → code 是 AJV 关键字,常见的有:

    code 含义
    type 类型不对(如应数字却是字符串)
    enum 不在枚举值里
    const 必须等于固定值
    format 格式不匹配
    additionalProperties 出现了 schema 没定义的字段
    required 缺少必填字段
    minLength / maxLength / pattern 字符串长度/正则
    minimum / maximum 数值越界
  2. 规则错误 → code 就是规则的 meta.id。无论是内置规则还是你用本 SDK 编写的外部规则,诊断的 code 字段即为规则 id,例如 csr-015-parent-object-existscsr-004-anchor-bus-type-namecode 字段即可,无需关心诊断的 source

小贴士:code 匹配大小写不敏感

注意:裸指令对没有 code 的诊断也生效;带 code 的指令只匹配确实带 code 的诊断——若某个错误没有 code,带码指令屏蔽不掉它,请改用裸指令。


五、几个常见疑问

Q:注释里只是提到 csr-ignore(比如 // see csr-ignore docs)会被误屏蔽吗?
不会。指令必须出现在注释开头,叙述性提及不生效。

Q:JSON 字符串值里的 // 会被当成注释吗?
不会。例如 "url": "http://x// csr-ignore" 里的 // 是字符串内容,不是指令。

Q:// csr-ignore: enum 写了但实际是 type 错误,会屏蔽吗?
不会。code 必须精确匹配,写错 code 不屏蔽——这能防止你"误屏蔽了一个不该屏蔽的错误"。对不上就改用裸 // csr-ignore

Q:多分片 catalog(primary + *_soft.sr / *_basic_info.sr)下,primary 里的注释能屏蔽兄弟分片的错误吗?
不能,也无需。屏蔽只对当前文件自己产生的错误生效:兄弟分片的错误在校验当前文件时本来就不显示。要屏蔽某个兄弟分片的错误,去那个分片文件本身里加注释。

Q:JSON 语法错误(比如少个逗号)能用 // csr-ignore 屏蔽吗?
不能。语法错误必须先修好(否则无法可靠解析文件),屏蔽只作用于"语法正确但违反 schema/规则"的诊断。

Q:屏蔽后 CI 还会报吗?
不会。校验引擎统一在收口处过滤被屏蔽的诊断,无论你通过 openubmc-meridarc CLI、CI 流水线还是 RuleTester 触发校验,屏蔽行为和结果都一致。


六、完整示例

// csr-ignore-file: additionalProperties   // 只放行整个文件的 additionalProperties 错误
{
    "FormatVersion": "3.00",
    "ManagementTopology": {
        "Anchor": { "Buses": ["I2c_2"] }
    },
    "Objects": {
        "Eeprom_NIC": {
            "Address": "${Slot} |> expr($1 == 1 ? 160 : 164)",  // csr-ignore: type
            "AddrWidth": 1
        },
        // csr-ignore-next-line
        "Event_OverTemp": {
            "@Default": { "Condition": 105 }
        },
        "NetworkPort_0": {
            "@Parent": "NetworkAdapter_1",  // csr-ignore: csr-015-parent-object-exists
            "MediumType": "Fiber",          // csr-ignore: enum
            "Position": "<=/PCIeDevice_1.Position |> string.format('%s',$1)"
                                            // csr-ignore: type,csr-027-string-function-correctness
        },
        "Legacy_Field": "keep me",   // csr-ignore
        "Chip_X": {
            "Type": 7                // csr-ignore: type,enum
        }
    }
}

七、最佳实践

  1. 优先精确、必要时裸屏蔽:能用 : code 精确屏蔽就别用裸指令,避免误伤同行其它错误。
  2. 留个原因:裸指令后面可跟说明文字(不影响识别),例如 // csr-ignore 误报:schema 未覆盖此业务字段,方便评审和日后清理。
  3. 定期清理:屏蔽是临时放行手段,升级 schema 或规则后记得回来复查,能去掉就去掉。
  4. 不要滥用 csr-ignore-file:整文件屏蔽会失去全部校验保护,仅用于临时跳过、并尽快恢复。
  5. 测试样例里慎用:在 RuleTester 用例中过度使用屏蔽会掩盖规则的真实行为,建议只在专门构造的"误报回归样例"里使用,并写明原因。