以下の記事で作った 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