LoginSignup
4
1

More than 5 years have passed since last update.

RuboCop 入門 #omotesandorb

Last updated at Posted at 2017-02-02
1 / 33

表参道.rb #19
https://omotesandorb.connpass.com/event/48967/

の発表資料。


自己紹介

名前: sinsoku
会社: 株式会社grooves
言語: Ruby
github: sinsoku
twitter: @sinsoku_listy


jobs.png


forkwell_cop.png


Forkwell_Scout_001.jpg


宣伝おわり


RuboCop 入門


RuboCop 入門

:beginner: RuboCop のコードを読む

:bug: 誤検知、エラーを直す

:cop: 新しい Cop を提案する


:beginner: RuboCop のコードを読む


たった 2 コマンド!簡単!

$ git clone https://github.com/bbatsov/rubocop.git
$ cd rubocop

ディレクトリ構成

lib/rubocop/
├  ast/
│  ├  node.rb
│  ├  traversal.rb
│  ├  ...
│
└  cop/
  ├  rails/
  │  ├  action_filter.rb
  │  ├  ...
  │
  ├  style/
  │  ├  access_modifier_indentation.rb
  │  ├  ...

イベント

lib/rubocop/ast/traversal.rb に on_xxx が書かれている

  • on_const
  • on_casgn
  • on_class
  • on_def
  • on_send
  • ... etc

:bug: 誤検知、エラーを直す


誤検知、エラー

  • 新しい Cop はわりと :bug: がある
    • v0.44.0 Rails/HttpPositionalArguments
    • v0.46.0 Rails/EnumUniqueness
  • 誤検知は英語だと false positive っぽい
    • 偽陽性 (検知してはいけないのに検知してしまう)
    • 偽陰性 (検知しなければいけないのに検知していない)

onk さんにコメントで教えていただきました。ありがとうございます!

onk.png


Enum はすぐ直されていた :-)

enum.png


既存 Cop の直し方

  1. Issue/PullRequest を見る
  2. 再現するテストを書く
  3. 直して PullRequest 投げる

先日直した Rails/Date

a string without timezone

'2017-02-02 19:30:00'.to_time(:utc) # bad
'2017-02-02 19:30:00 +09:00'.to_time(:utc) # good

テストコード

context 'when a string literal with timezone' do
  it 'does not register an offense' do
    inspect_source(cop, '"2016-07-12 14:36:31 +0100".to_time(:utc)')
    expect(cop.offenses).to be_empty
  end
end

context 'when a string literal without timezone' do
  it 'registers an offense' do
    inspect_source(cop, '"2016-07-12 14:36:31".to_time(:utc)')
    expect(cop.offenses.size).to eq(1)
  end
end

実装

def on_send(node)
  receiver, method_name = *node
  return unless receiver && bad_methods.include?(method_name)

  chain = extract_method_chain(node)
  return if safe_chain?(chain)

  return if method_name == :to_time && safe_to_time?(node)

  add_offense(node, :selector,
              format(MSG_SEND,
                     method_name))
end

実装

def safe_to_time?(node)
  receiver, _method_name, *args = *node
  if receiver.str_type?
    zone_regexp = /[+-][\d:]+\z/
    receiver.str_content.match(zone_regexp)
  else
    args.length == 1
  end
end

後はプルリクを 英語 で投げるだけ


英語力...(´・ω・)

comment.png


マージされた :tada:

pullreq.png


:cop: 新しい Cop を提案する


経緯

pr.png


気づけなかった...orz


自動化しよう(`・ω・´)


新規 Cop の直し方

  1. Issue/PullRequest を見る
  2. テストを書く
  3. 実装して PullRequest 投げる

デモ


まとめ


もっとレビューを楽にしよう!

matome.png


ご清聴ありがとうございました!!

4
1
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
4
1