`Style/EmptyCaseCondition` copのautocorrectでコメントがなくなるケースを直した

少し前にフィードバックをもらっていたイシューとなる。

github.com

以下のように、case と最初の when の間にあるソースコードコメントが autocorrect で消えるというフィードバックだった。

def foo
  case
  # when bar ...
  when bar
    2
  end
end

プロダクトコードのパッチは以下で、case から最初の when までの範囲を if に autocorrect 置換していたのを、case を削除して最初の whenif に置換することでコメントを維持するようにした。

        private

        def correct_case_when(corrector, case_node, when_nodes)
-         case_range = case_node.loc.keyword.join(when_nodes.first.loc.keyword)
-
-         corrector.replace(case_range, 'if')
+         remove_case_node(corrector, case_node)
+         corrector.replace(when_nodes.first.loc.keyword, 'if')

          when_nodes[1..-1].each do |when_node|
            corrector.replace(when_node.loc.keyword, 'elsif')
@@ -88,6 +87,14 @@ def correct_when_conditions(corrector, when_nodes)
            corrector.replace(range, conditions.map(&:source).join(' || '))
          end
        end
+
+       def remove_case_node(corrector, case_node)
+         range = range_by_whole_lines(
+           case_node.loc.keyword, include_final_newline: true
+         )
+         corrector.remove(range)
+       end
      end
    end
  end

range_by_whole_lines(case_node.loc.keyword, include_final_newline: true)range_by_whole_lines メソッドと include_final_newline: true オプションが伝家の宝刀で、case について行末改行までを対象とした範囲を得ることができる。

(余談だが、private メソッドに切り出しているのは諸々の Cop に引っかかる都合上 Extract Method した結果となる。)

以下のようにコメントが維持されるようになっている。

Before

def foo
  if bar
    2
  end
end

After

def foo
  # when bar ...
  if bar
    2
  end
end

github.com