All About RuboCop (Saint P RubyConf)

All About RuboCop (Saint P RubyConf)

Slide-deck from my talk at the Saint P RubyConf 2018 in Saint Petersburg, Russia.

1be785d1d788b82929e55fc83a9f0aaa?s=128

Bozhidar Batsov

August 12, 2018
Tweet

Transcript

  1. 1.
  2. 7.
  3. 13.
  4. 14.
  5. 16.
  6. 17.
  7. 20.
  8. 21.
  9. 23.
  10. 24.
  11. 25.
  12. 26.
  13. 28.
  14. 29.
  15. 30.
  16. 31.
  17. 39.
  18. 40.
  19. 50.
  20. 56.
  21. 57.
  22. 66.
  23. 69.
  24. 71.
  25. 73.
  26. 74.
  27. 77.
  28. 85.

    pry(main)> Ripper.sexp('alias :some :test') => [:program, [[:alias, [:symbol_literal, [:symbol, [:@ident,

    "some", [1, 7]]]], [:symbol_literal, [:symbol, [:@ident, "test", [1, 13]]]]]]]
  29. 86.

    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
  30. 88.

    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"]]
  31. 89.

    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, ")"]]
  32. 91.
  33. 92.
  34. 97.
  35. 101.

    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 # "+"
  36. 102.

    $ 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
  37. 104.
  38. 109.
  39. 114.
  40. 116.
  41. 121.

    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)
  42. 122.

    Style/ArrayJoin (now) def_node_matcher :join_candidate?, '(send $array :* $str)' def on_send(node)

    join_candidate?(node) { add_offense(node, location: :selector) } end
  43. 149.

    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
  44. 151.
  45. 152.
  46. 153.
  47. 162.

    “Using RuboCop is exciting. You never know if —auto-correct is

    going to work or not!” — Dick Sutterer
  48. 163.

    RuboCop changed my life! I used to go to horror

    movies to get an adrenaline rush - now I simply upgrade RuboCop! — Anton Devilov
  49. 164.
  50. 171.

    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)
  51. 175.

    Come up with a less painful process for dealing with

    new cops and configuration changes
  52. 178.

    Breaking changes •Cop API changes •Extension API changes •Dropping support

    for Ruby versions •Renaming/removing cops •Renaming/changing/removing config values
  53. 183.

    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
  54. 184.
  55. 188.