已合并
fix(merge_proto): 修复带注释/预处理守卫的proto解析,避免误吞额外内容 #1095
liu-wei创建于 7月7日
fix(merge_proto): 修复带注释/预处理守卫的proto解析,避免误吞额外内容 #1095
已合并
liu-wei创建于 7月7日
liu-wei
liu-wei成员
7月7日

描述

scripts/util/merge_proto.pymatch_op_proto / match_op_proto_extend 函数内 hard-code 的 regex 有 bug:在带 前置注释头文件 guard 的 proto 文件上,贪婪匹配会误吞额外内容,导致 opname 错位或 op_def 包含不该有的头部。

Bug 复现

旧 regex:

re.compile(r"REG_OP\((.+)\).*OP_END_FACTORY_REG\(\1\)", re.DOTALL)

对如下典型 proto 文件:

/* Copyright header ... */
#ifndef OP_AAA_PROTO_H_
#define OP_AAA_PROTO_H_

REG_OP(Add) ...
OP_END_FACTORY_REG(Add)

#endif

贪婪 (.+)尽量多匹配,跨过注释 + guard 一直吃到文件末尾的最后一个 ),导致:

  • opname 捕获到的是 Add) ... OP_END_FACTORY_REG(Add不是预期的 Add
  • backreference \1 强制 opname 在 OP_END_FACTORY_REG(...)再出现一次——大多数情况整个 match 失败match_op_proto 返回 None

修复方案

把 hard-coded regex 提到模块级 OP_DEF_PATTERN 统一两处复用:

OP_DEF_PATTERN = re.compile(
    r"(?:[ \t]*/\*\*?(?:[^*]|\*(?!/))*?\*/[ \t]*\n\s*)?"
    r"(?P<guard>[ \t]*#\s*ifndef\s+\w+[^\n]*\n"
    r"[ \t]*#\s*define\s+\w+[^\n]*\n\s*)?"
    r"REG_OP\((?P<opname>.+?)\)"
    r".*?OP_END_FACTORY_REG\((?P=opname)\)"
    r"(?(guard)[^\n]*\n[ \t]*#\s*endif[^\n]*)",
    re.DOTALL,
)

4 个关键改动

改动 修复什么
OP_DEF_PATTERN 模块级常量 性能(编译 1 次 vs 2 次)+ 行为一致(两处不会漂移)
(?P<opname>.+?) 非贪婪 关键修复:贪婪 (.+) 在多 op / 带注释文件上会误吞内容
(?P<opdef>...) 包裹 REG_OP 块 + op_def = match.group("opdef") 关键修复:只取 REG_OP 内部,op_def 不再带前置注释 / guard(避免下游 merge_op_proto 拼接时 N 份 license 重复)
(?(guard)...#endif...) 条件回溯 捕获完整的 #ifndef / #define / REG_OP / #endif 三件套;如果有 guard 就必有 endif,缺一即不匹配(坏源不放过)
match.group("opname") 替代 match.group(1) 命名组比数字下标可读,扩展时不依赖顺序
文件末尾补换行 POSIX 规范

关键设计点:为什么 op_defopdef group 而不用 group(0)

match.group(0) 包含整段匹配(comment + guard + REG_OP + #endif)。match.group("opdef") 只包含 REG_OP(...)...OP_END_FACTORY_REG(...) 内部。

为什么不带 comment / guard 进 op_def

  • 下游 merge_op_proto 拼接到合并文件时会重复 N 份 license 注释和头文件保护(N = proto 文件数)
  • op_def 只需要 op 自身定义,注释/guard 是源文件层的语义,跨文件合并时不应该重复

关联的Issue

Fixes #605

测试

需补充的测试场景(当前 PR 缺 test,可作为 follow-up):

场景 期望
标准 proto(无 comment/guard) 旧行为完全等价:opname=Add, op_def=Add REG_OP 块
带 copyright 注释 + guard 的标准 proto 新行为可正确解析(旧 regex 失败
1 个 proto 文件含 2 个 op,共享同一组 guard finditer 正确返回 2 个 match,opname 各自正确
#pragma once 而非 #ifndef 的 proto guard group 不匹配(fall back 到只匹配 REG_OP 块),降级而非崩溃
#endif(坏源)的 proto 条件回溯失败 → match.group("opdef") 不匹配,函数返回 None(不静默吞错)
文件全为 // 行注释 + 无 /* */ comment group 不匹配(content 是 [^*] 仍 ok),只匹配 REG_OP

文档更新

无(build 工具细节,不需要用户文档)

类型标签

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 liu-wei 的贡献)
liu-weiliu-wei成员
7月7日 创建了 pull request,commit f9aca14b
atomgit-bot
atomgit-bot
7月7日 评论:

变更摘要

此 PR 修复了 scripts/util/merge_proto.py 中 proto 文件解析的正则表达式问题。原有的 REG_OP(...)...OP_END_FACTORY_REG(...) 模式在遇到操作定义前带有注释块(/** ... */)或预处理守卫(#ifndef/#define/#endif)时,会错误地将匹配边界扩展到文件中最先出现的 REG_OP,从而"误吞"额外的无关内容。修复方案是将正则提取为模块级 OP_DEF_PATTERN,在其中将注释和预处理守卫作为可选前缀/后缀,并使用命名捕获组(opnameopdef)精确提取操作名和操作定义本身,使 match_op_protomatch_op_proto_extend 两个函数均受益。

主要改动

  • 新增模块级正则 OP_DEF_PATTERN:在文件顶部定义了一个完整的正则表达式,支持可选的 /** ... */ 注释块、可选的 #ifndef/#define 预处理守卫、以及 REG_OP(name)...OP_END_FACTORY_REG(name) 操作定义与可选的 #endif 收尾,使用命名捕获组区分守卫与操作定义。
  • match_op_proto 改用新正则:将原先内联构造的 op_def_pattern 替换为模块级 OP_DEF_PATTERN,并通过 match.group("opname")match.group("opdef") 获取结果,避免回退引用 \1 可能匹配到错误内容。
  • match_op_proto_extend 同步更新:同样替换为 OP_DEF_PATTERN.finditer 并使用命名捕获组获取每次匹配的操作名和操作定义,使多个操作定义场景下的解析保持一致且准确。
likedislike
atomgit-bot
atomgit-bot
7月7日 评论:

代码审查

审查总结

对变更文件 scripts/util/merge_proto.py 进行了全面审查,分析结果:

  • P0: 0 个
  • P1: 0 个
  • P2: 0 个
  • P3: 1 个

已审查的文件

  • scripts/util/merge_proto.py — 发现 1 个 P3 问题(条件 #endif 匹配过于严格,守卫特性为死代码)

整体风险评估:低风险。此变更将行内编译的正则表达式提升为模块级预编译常量,并用命名捕获组替代数字索引,提升了代码可读性和可维护性。新增的 doc comment 和预处理守卫匹配逻辑对于当前仓库中的所有实际 proto 文件均能正确回退到核心 REG_OP 块匹配,不会产生错误输出。唯一的低优先级问题是守卫+endif 条件匹配过于严格导致该子特性在当前仓库中从未生效,但回退行为保证了功能正确性。

⚠️ 已识别出整体风险,但无法提取行内评论,请参考整体评估。

likedislike
CANN-robotCANN-robot成员
7月7日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
7月7日 评论:

CLA Signature Pass

liu-wei, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
CANN-robot
CANN-robot成员
7月7日 评论:

Thanks for your pull-request.
The full list of commands accepted by me can be found at here
You can get sig-info at here


PR Approval Progress

Congratulations! All modules have met the lgtm and approve requirements.

Module Approval Details

module lgtm status approve status
repo-cann/ops-cv 王林木, 张磊 (2/2) 王林木, 张磊 (2/1)

💡 Tip:

  • Committer can comment /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)
likedislike
CANN-robotCANN-robot成员
7月7日 将zhou-qilong,rxtfeng,loov1,zl_hw,llimwang,gubaocheng设为评审人
CANN-robotCANN-robot成员
7月7日 将zhou-qilong,rxtfeng,loov1,zl_hw,llimwang,gubaocheng设为审查人
liu-weiliu-wei成员
7月7日 修改了pull request 的描述
liu-wei
liu-wei成员
7月7日 评论:

compile

likedislike
liu-weiliu-wei成员
7月7日 update merge request[project id: 7657293, iid: 1095, commit_id: 335d7e3c57c41a9e16c7014d82b8b2e6f06a82df] virtual merging success
CANN-robotCANN-robot成员
7月7日 添加了label:ci-pipeline-running
CANN-robot
CANN-robot成员
7月7日 评论:

流水线任务触发成功
任务链接 [5cf0e33450cf4422b4598b6b6576098b][流水线指导]

任务名称状态日志下载链接
Compile_Ascend_X86 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_mobile_station ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_experimental ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_experimental ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_A5 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_A5 ✅ SUCCESS >>>>> >>>>>
pre_comment ✅ SUCCESS >>>>>
Compile_Pre ✅ SUCCESS >>>>>
Compile_Ascend_X86_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_mobile_station_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_experimental_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_A5_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_experimental_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_A5_ubuntu24 ✅ SUCCESS >>>>> >>>>>
Compile_X86_monitor_910b ✅ SUCCESS >>>>> >>>>>
Compile_X86_monitor_910c ✅ SUCCESS >>>>> >>>>>
Compile_X86_monitor_950 ✅ SUCCESS >>>>> >>>>>
Compile_classify ✅ SUCCESS >>>>>
Compile_harmony-infer-chs-cv ✅ SUCCESS >>>>>
Compile_harmony-infer-chs-cv-1 ✅ SUCCESS >>>>>
UT_Test ✅ SUCCESS
PreSmoke_A900 ✅ SUCCESS >>>>>
API_Check ✅ SUCCESS >>>>>
PreSmoke_ATK_Test_A2 ✅ SUCCESS >>>>>
UT_Test_report_lcov ✅ SUCCESS

[2026-07-07 17:26:25]    CI执行结束

likedislike
CANN-robot
CANN-robot成员
7月7日 评论:

流水线任务触发成功
任务链接 [57faf48597fe40e9862434baedc8364f][流水线指导]

任务名称状态日志下载链接
codecheck ✅ SUCCESS >>>>>
SCA ✅ SUCCESS >>>>>
antipoison ✅ SUCCESS >>>>>
codecheck_checkpr ✅ SUCCESS
StaticCheck_codespell_check ✅ SUCCESS
StaticCheck_link_validity_check ✅ SUCCESS
StaticCheck_resource_existence_check ✅ SUCCESS
StaticCheck_tag_closed_check ✅ SUCCESS
StaticCheck_markdownlint ✅ SUCCESS
codecheck_codestyle ✅ SUCCESS >>>>>
codecheck_precommit ✅ SUCCESS >>>>>

[2026-07-07 17:22:48]    CI执行结束

likedislike
CANN-robotCANN-robot成员
7月7日 添加了label:api-check-pass
CANN-robotCANN-robot成员
7月7日 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
7月7日 添加了label:ci-pipeline-passed
liu-weiliu-wei成员
7月8日 修改了pull request 的描述
llimwang成员
7月8日 评论:

/approve

likedislike
CANN-robotCANN-robot成员
7月8日 添加了label:approved
zl_hw成员
7月8日 评论:

/lgtm
/approve

likedislike
CANN-robotCANN-robot成员
7月8日 添加了label:lgtm
CANN-robotCANN-robot成员
7月8日 关闭了关联的issue
CANN-robotCANN-robot成员
7月8日 合入了pull request