LoginSignup
0
3

More than 5 years have passed since last update.

Synvert で作ったリファクタリング用の Snippet を RuboCop に置き換える

Posted at

以下の記事で作った Synvert の Snippet を RuboCop の --auto-correct で置き換えてみます。

RuboCop の Cop の作り方

RuboCop が提供している RuboCop::Cop::Cop クラスを継承して作成します。

詳細な作成方法については下記の記事をご確認ください。

実践!! RuboCopプラグイン開発入門 - SideCI TechBlog

Synvert の例と同じ変換処理を RuboCop でも実装してみます。
実践!! RuboCopプラグイン開発入門の手順に沿って実装してみました。
件の記事を読めばわかるところは省いて、Copの本体のコードだけ紹介。

テスト対象コード

10.times do
  a = rand(-5..5)
  if a > 0
    puts "positive"
  elsif a < 0
    puts "negative"
  else
    puts "zero"
  end
end

変換コード

# frozen_string_literal: true

module RuboCop
  module Cop
    module Lint
      class NegaPosi < Cop
        MSG_NEGA = 'X < 0 は X.negative? 変更してください'.freeze
        MSG_POSI = 'X > 0 は X.positive? に変更してください'.freeze
        METHOD_NEGA = "negative?"
        METHOD_POSI = "positive?"

        def on_send(node)
          receiver, method_name, *args = *node
          return unless [:>, :<].include?(method_name)
          return unless args.first.source == "0"
          message = method_name == :> ? MSG_POSI : MSG_NEGA
          add_offense(node, :expression, message)
        end

        def autocorrect(node)
          _receiver, method_name, *args = *node
          nega_posi = method_name == :> ? METHOD_POSI : METHOD_NEGA
          lambda do |corrector|
            corrector.replace(node.loc.expression, replacement(node, nega_posi))
          end
        end

        private

        def replacement(node, nega_posi)
          "#{node.receiver.source}.#{nega_posi}"
        end
      end
    end
  end
end

実行

  • lint を実行
$ rubocop  -r rubocop/nega_posi test/sample.rb
Inspecting 1 file
W

Offenses:

test/sample.rb:3:6: W: Lint/NegaPosi: X > 0 は X.positive? に変更してください
  if a > 0
     ^^^^^
test/sample.rb:5:9: W: Lint/NegaPosi: X < 0 は X.negative? 変更してください
  elsif a < 0
        ^^^^^

1 file inspected, 2 offenses detected
  • autocorrect を実行
$ rubocop --auto-correct  -r rubocop/nega_posi test/sample.rb
Inspecting 1 file
W

Offenses:

test/sample.rb:3:6: W: [Corrected] Lint/NegaPosi: X > 0 は X.positive? に変更してください
  if a > 0
     ^^^^^
test/sample.rb:5:9: W: [Corrected] Lint/NegaPosi: X < 0 は X.negative? 変更してください
  elsif a < 0
        ^^^^^

1 file inspected, 2 offenses detected, 2 offenses corrected
  • 実行後のファイル
10.times do
  a = rand(-5..5)
  if a.positive?
    puts "positive"
  elsif a.negative?
    puts "negative"
  else
    puts "zero"
  end
end
  • diff

diff.png

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3