Layout/EmptyLinesAroundAccessModifier
で発生する RuboCop の Infinite loop エラーを直した。
rubocop-hq/rubocop#6507 で直した問題の裏で起きていたリグレッションだった。
Layout/EmptyLinesAroundAccessModifier
と Layout/EmptyLinesAroundClassBody
の auto-correct がカチあって無限ループになる。
以下のようなコードがあるとして Layout/EmptyLinesAroundAccessModifier
による auto-correct をする。
% cat example.rb class SomeController < SomeOtherController def index; end private end % rubocop example.rb --only Layout/EmptyLinesAroundAccessModifier -a Inspecting 1 file C Offenses: example.rb:4:3: C: [Corrected] Layout/EmptyLinesAroundAccessModifier: Keep a blank line before and after private. private ^^^^^^^ 1 file inspected, 1 offense detected, 1 offense corrected
以下のように private
修飾子の後ろに改行を入れる。これは false positive に起因しており end
の前に private
が置かれている場合は空行は無視されるのが期待したものだった。
% cat example.rb
class SomeController < SomeOtherController
def index; end
private
+
end
この状態で Layout/EmptyLinesAroundClassBody
での auto-correct をする。
% rubocop example.rb --only Layout/EmptyLinesAroundClassBody -a Inspecting 1 file C Offenses: example.rb:5:1: C: [Corrected] Layout/EmptyLinesAroundClassBody: Extra empty line detected at class body end. 1 file inspected, 1 offense detected, 1 offense corrected
今度は private
の後ろの空行を削除する。
% cat example.rb
class SomeController < SomeOtherController
def index; end
private
-
end
このように空行を入れたり消したりという無限ループになっていた。
問題はスーパークラスがある場合にスーパークラスに対応する最終行の位置をとっていたことだった。これは冒頭でエンバグを入れた以下のようにスーパークラスの指定前で改行するケースへのパッチでの解決がよくなかった。
class SomeController < SomeOtherController def index; end private end
その解決として、class
宣言に対応する end
の位置となる最終行を個別にとっておいて参照するようにしたのが本パッチだった。