Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

All About RuboCop (RubyKaigi 2018)

All About RuboCop (RubyKaigi 2018)

Slide deck from my talk at RubyKaigi 2018 in Sendai.

Bozhidar Batsov

May 31, 2018
Tweet

More Decks by Bozhidar Batsov

Other Decks in Programming

Transcript

  1. Improve Ruby coding style rules and Lint by Koichi Ito

    http://rubykaigi.org/2018/presentations/koic.html#jun01
  2. Notable Japanese Contributors • Yuji Nakayama (@yujinakayama) • Masataka Kuwabara

    (@pocke) • Koichi Ito (@koic) • Yukihiro "Matz" Matsumoto (@matz) ;-)
  3. pry(main)> Ripper.sexp('alias :some :test') => [:program, [[:alias, [:symbol_literal, [:symbol, [:@ident,

    "some", [1, 7]]]], [:symbol_literal, [:symbol, [:@ident, "test", [1, 13]]]]]]]
  4. each(:method_add_arg, sexp) do |s| next if s[1][0] != :call receiver

    = s[1][1][1] method_name = s[1][3][1] if receiver && receiver[1] == 'Array' && method_name == 'new' && s[2] == [:arg_paren, nil] offences.delete(Offence.new(:convention, receiver[2].lineno, ERROR_MESSAGE)) add_offence(:convention, receiver[2].lineno, ERROR_MESSAGE) end end
  5. pry(main)> Ripper.lex(':one') => [[[1, 0], :on_symbeg, ":"], [[1, 1], :on_ident,

    "one"]] pry(main)> Ripper.lex(':alias') => [[[1, 0], :on_symbeg, ":"], [[1, 1], :on_kw, "alias"]]
  6. pry(main)> Ripper.lex('def alias(arg)')
 => [[[1, 0], :on_kw, "def"],
 [[1, 3],

    :on_sp, " "],
 [[1, 4], :on_kw, "alias"],
 [[1, 9], :on_lparen, "("],
 [[1, 10], :on_ident, “arg"],
 [[1, 13], :on_rparen, ")"]] pry(main)> Ripper.lex('def aliass(arg)')
 => [[[1, 0], :on_kw, "def"],
 [[1, 3], :on_sp, " "],
 [[1, 4], :on_ident, "aliass"],
 [[1, 10], :on_lparen, "("],
 [[1, 11], :on_ident, "arg"],
 [[1, 14], :on_rparen, ")"]]
  7. p Parser::CurrentRuby.parse("2 + 2").loc # #<Parser::Source::Map::Send:0x007fe5a1ac2388 # @dot=nil, # @begin=nil,

    # @end=nil, # @selector=#<Source::Range (string) 2...3>, # @expression=#<Source::Range (string) 0...5>> p Parser::CurrentRuby.parse("2 + 2").loc.selector.source # "+"
  8. $ ruby-parse -L -e "2+2" (send (int 2) :+ (int

    2)) 2+2 ~ selector ~~~ expression (int 2) 2+2 ~ expression (int 2) 2+2 ~ expression
  9. def on_send(node) receiver_node, method_name, *arg_nodes = *node return unless receiver_node

    && receiver_node.array_type? && method_name == :* && arg_nodes.first.str_type? add_offense(node, location: :selector) end Style/ArrayJoin (before)
  10. Style/ArrayJoin (now) def_node_matcher :join_candidate?, '(send $array :* $str)' def on_send(node)

    join_candidate?(node) { add_offense(node, location: :selector) } end
  11. class SimplifyNotEmptyWithAny < Cop MSG = 'Use `.any?` and remove

    the negation part.'.freeze def_node_matcher :not_empty_call?, <<-PATTERN (send (send (...) :empty?) :!) PATTERN def on_send(node) return unless not_empty_call?(node) add_offense(node) end end
  12. RuboCop HQ •RuboCop •RuboCop JP •RuboCop RSpec/Rails/Performance •guard-rubocop, etc •Ruby

    & Rails Style Guides •Libraries extracted from RuboCop (e.g. node extensions, node pattern matching, etc)
  13. Come up with a less painful process for dealing with

    new cops and configuration changes
  14. Breaking changes •Cop API changes •Extension API changes •Dropping support

    for Ruby versions •Renaming/removing cops •Renaming/changing/removing config values
  15. RuboCop.org •Easy to navigate & mobile-friendly •Published using MkDocs (or

    similar) •Separate User and Developer manual •Getter getting started resources (e.g. video tutorials) •Improved cop documentation