DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

RuboCop 把 fetch 展开参数再加默认值,修正 RedundantFetchBlock 的参数判断

RuboCop 的 fetch 块修正曾把展开参数当成单个实参,追加默认值后造成参数数量错误。1.92.0 包含保护,应核对修正产物和缺省分支行为。

给 Hash#fetch 提供展开参数,再用块处理缺省值,Ruby 可以正常执行;但自动修正后突然报参数数量错误,要检查 Style/RedundantFetchBlock 是否把块内容追加进了原参数列表。

args = [:missing, :default]
hash = {}
hash.fetch(*args) { 5 }

这里展开后已经有键和默认值。Ruby 在键不存在时优先执行块,返回 5。如果修正成下面这样,就变成了三个参数:

hash.fetch(*args, 5)
# ArgumentError: wrong number of arguments

故障组合有 RuboCop 1.90.0 的明确案例。关键不在块是否只含一个字面量,而在展开参数的实际数量无法从一个 AST 参数节点推算。*args 在语法树中占一个节点,执行时却可以贡献多个参数。把“一个语法节点”当成“一个运行参数”,就会生成非法调用。

RuboCop 1.92.0 包含这条转换的保护:遇到展开参数、转发剩余参数等不能安全追加默认值的形式,保留原调用。不能据此断言所有更早版本都出现此故障,也不必把所有 fetch 块都改写。

在 Gemfile 中提高已有 RuboCop 版本约束,使解析结果包含 1.92.0,再更新锁文件:

bundle update rubocop
bundle exec rubocop --version
bundle exec rubocop --only Style/RedundantFetchBlock example.rb

还不能更新工具时,可以在最小范围暂停这条自动修正,并保留块:

# rubocop:disable Style/RedundantFetchBlock
hash.fetch(*args) { 5 }
# rubocop:enable Style/RedundantFetchBlock

修复验收需要同时看输出代码和运行结果。原例在缺失键时应返回 5;补一个已存在的键,应返回存储值。再检查参数数组只有键、包含键和默认值两种情况。扫描退出成功不能代替这些行为检查。

如果自动修正已经进入仓库,先从修正前的代码恢复有块的调用,再重新检查。直接删掉新增参数可能把缺省分支从返回值改成异常;展开参数本来就含默认值时,也不能随手把块换成该默认值。