ActiveRecord Association Extensionとwith_optionsを併用するとrubocop-railsのRails/HasManyOrHasOneDependent警告が出るので修正してみた - valid,invalid でrubocopの中身に少し興味を持ったのでシュッと倒せそうなissueがないかを拙作の goofi で検索してみたところ、過去に遭遇したことあるバグを見かけたので対応してpull requestを送ってみた。
事象
issueはこれ Faulty calculation in UncommunicativeName · Issue #8229 · rubocop-hq/rubocop · GitHub
Naming/MethodParameterName
, Naming/BlockParameterName
copsで警告する対象に _
や*
といったprefixが付いていると警告の表示位置がずれる…、実際の挙動を見たほうがわかりやすい。
以下のファイルがあるとする。
def test1(_a); end def test2(__a); end def test3(*a); end def test4(**a); end def test5(**__a); end
rubocopを実行すると、警告箇所を示すlocation ^
が引数名の全体にかかっていないことがわかる。
$ rubocop test.rb Inspecting 1 file C Offenses: test.rb:3:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test1(_a); end ^ test.rb:5:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test2(__a); end ^ test.rb:7:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test3(*a); end ^ test.rb:9:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test4(**a); end ^ test.rb:11:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test5(**__a); end ^ 1 file inspected, 5 offenses detected
本来はこうあるべき。
$ rubocop test.rb Inspecting 1 file C Offenses: test.rb:3:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test1(_a); end ^^ test.rb:5:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test2(__a); end ^^^ test.rb:7:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test3(*a); end ^^ test.rb:9:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test4(**a); end ^^^ test.rb:11:11: C: Naming/MethodParameterName: Method parameter must be at least 3 characters long. def test5(**__a); end ^^^^^ 1 file inspected, 5 offenses detected
修正
Naming/MethodParameterName
, Naming/BlockParameterName
copsでincludeしているUncommunicativeName
moduleにて、引数名の長さの計算が誤っていたようだ。
def check(node, args) args.each do |arg| # Argument names might be "_" or prefixed with "_" to indicate they # are unused. Trim away this prefix and only analyse the basename. name_child = arg.children.first next if name_child.nil? full_name = name_child.to_s next if full_name == '_' name = full_name.gsub(/\A(_+)/, '') next if allowed_names.include?(name) # name.size が location の range を決めている # name は prefix を除いた文字列 range = arg_range(arg, name.size) issue_offenses(node, range, name) end end
length
を愚直に再計算して渡すようにした。
def check(node, args) args.each do |arg| # Argument names might be "_" or prefixed with "_" to indicate they # are unused. Trim away this prefix and only analyse the basename. name_child = arg.children.first next if name_child.nil? full_name = name_child.to_s next if full_name == '_' name = full_name.gsub(/\A(_+)/, '') next if allowed_names.include?(name) - range = arg_range(arg, name.size) + length = full_name.size + length += 1 if arg.restarg_type? + length += 2 if arg.kwrestarg_type? + range = arg_range(arg, length) issue_offenses(node, range, name) end end
rubocopへのpull requestは初めてだったがシュッとマージしてもらえて良かった。
環境
- rubocop 1.8.0
This article is for ohbarye Advent Calendar 2020.