Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
All About RuboCop (RubyKaigi 2018)
Bozhidar Batsov
May 31, 2018
Programming
4
8.1k
All About RuboCop (RubyKaigi 2018)
Slide deck from my talk at RubyKaigi 2018 in Sendai.
Bozhidar Batsov
May 31, 2018
Tweet
Share
More Decks by Bozhidar Batsov
See All by Bozhidar Batsov
Victims of Complexity
bbatsov
0
230
Ruby 3.0 Redux (Spark Academy, Jan 2021)
bbatsov
1
170
Ruby 3.0 Redux (Pivorak 4.0)
bbatsov
0
380
The Elements of Programming Style (HackConf 2019)
bbatsov
0
140
The Groundhog Day Development Method (HackConf 2019)
bbatsov
0
180
CIDER Distilled: A Common Foundation for Clojure Tooling
bbatsov
0
110
Ruby 3.0: Redux (Saint P RubyConf 2019)
bbatsov
0
170
Ruby 3 Redux
bbatsov
0
270
nREPL Redux (DCD 2019)
bbatsov
1
340
Other Decks in Programming
See All in Programming
Computer Vision Seminar 1/コンピュータビジョンセミナーvol.1 OpenCV活用
fixstars
0
140
プロダクトの成長とSREと
takuyatezuka
0
120
SAM × Dockerでサーバーレス開発が超捗った話
yu_yukk_y
1
120
段階的な技術的負債の解消方法.pdf
ko2ic
2
890
「混ぜるな危険」を推進する設計
minodriven
8
2.5k
ゴーファーくんと辿るプログラミング言語の歴史/history-of-programming-languages-with-gopher
iwasiman
11
4.9k
Reactは何を提供するLibraryなのか?
taro28
6
920
ふんわり理解するcontext
rukiadia
1
180
20220706_Google Apps Scriptを実演で学ぶ~ GAS × Slack ~
apachan
2
620
このタイミングで知っておきたい 開発生産性の高いエンジニア組織の特徴とは / dev-sumi-20220721-productivity-features
findyinc
7
2.6k
NestJS_meetup_atamaplus
atamaplus
0
210
How GitHub Supports Vim License Detection, The Five Years Journey
othree
1
350
Featured
See All Featured
Creatively Recalculating Your Daily Design Routine
revolveconf
207
10k
10 Git Anti Patterns You Should be Aware of
lemiorhan
638
52k
The Straight Up "How To Draw Better" Workshop
denniskardys
225
120k
Designing with Data
zakiwarfel
91
4k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
181
15k
Automating Front-end Workflow
addyosmani
1351
200k
Keith and Marios Guide to Fast Websites
keithpitt
404
21k
Why Our Code Smells
bkeepers
PRO
324
55k
Support Driven Design
roundedbygravity
87
8.6k
For a Future-Friendly Web
brad_frost
166
7.5k
Fireside Chat
paigeccino
13
1.4k
Building Applications with DynamoDB
mza
84
4.8k
Transcript
Hello!
Божидар
None
Bozhidar
Божo
Bozho cool
Bozo not cool
Bozho is not a bozo!
Bozho is not a bozo! (at least he claims so)
Bug cool
(The RuboCop Guy)
Sofia, Bulgaria Sofia, Bulgaria
None
Grigor Dimitrov vs Kei Nishikori
None
Lukanka
Bulgarian Cheese
Rakia Connecting People
Shopska Salad (use only with Rakia)
None
bbatsov
Ruby & Rails style guides
None
None
None
None
First time in Japan!!!
None
None
None
None
None
None
All About RuboCop by Bozhidar Batsov (a.k.a. bug)
Writing Lint for Ruby by Masataka Kuwabara (a.k.a. Pocke) http://rubykaigi.org/2017/presentations/p_ck_.html
Improve Ruby coding style rules and Lint by Koichi Ito
http://rubykaigi.org/2018/presentations/koic.html#jun01
Something About RuboCop by Bozhidar Batsov (a.k.a. bug)
RuboCop in a Nutshell
A Ruby static code analysis tool aimed to enforce the
Ruby Community Style Guide
In other words…
It keeps your codebase consistent
It saves you time
It advances the Ruby language forward
None
32,608,128
Provides an efficient way for codebases to be updated
Disclaimer
Lint tools are not a replacement for common sense
Why an entire talk about a mere lint tool?
None
None
Notable Japanese Contributors • Yuji Nakayama (@yujinakayama) • Masataka Kuwabara
(@pocke) • Koichi Ito (@koic) • Yukihiro "Matz" Matsumoto (@matz) ;-)
None
https://github.com/rubocop-jp/issues
https://github.com/fortissimo1997/ruby-style-guide
314 open issues
100 volunteers
3.14 issues/person
Coincidence?
Or providence?
A Brief History of Time
A Brief History of RuboCop
2011 The Ruby Style Guide
None
May, 2012 RuboCop 0.0.0
May, 2012 RuboCop 0.0.0
None
Static code analysis with regular expressions …
None
Nov, 2012 Along Came Jonas
None
None
Spring, 2013 Return of the Jedi
Using a proper parser!
None
Struggles with Ripper
Ripper supported only MRI
I wanted to build a cross-platform tool
Ripper had (has?) almost no documentation
Ripper is tied to the underlying Ruby runtime
…which means you can’t parse code as Ruby 2.3 while
running Ruby 2.5
Ripper has a very hard to work with AST representation
pry(main)> Ripper.sexp('alias :some :test') => [:program, [[:alias, [:symbol_literal, [:symbol, [:@ident,
"some", [1, 7]]]], [:symbol_literal, [:symbol, [:@ident, "test", [1, 13]]]]]]]
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
And many quirks…
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"]]
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, ")"]]
Which no one really considered problematic…
None
None
Parser: A New Hope
parser is cross-platform
well documented
supports multiple parsing targets (Ruby 1.9 - 2.5)
None
easy to work with ast format https://github.com/whitequark/ast
p Parser::CurrentRuby.parse("2 + 2") # (send # (int 2) :+
# (int 2))
AST node source location mappings
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 # "+"
$ 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
powerful code rewriting capabilities
None
Struggles with Parser
Parser was brand new
Had no real users
And had plenty of bugs…
None
Peter Zotov (@whitequark)
28th May, 2013 State of Unity
RuboCop 0.8
1st July, 2013 RuboCop 0.9
Formatters
Auto-correct
None
Commissioner (single parsing run triggers all cops)
Results caching (rubocop —-cache)
Parallel Checks (rubocop —-parallel)
Pattern Matching (regex-style matching for ast nodes)
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)
Style/ArrayJoin (now) def_node_matcher :join_candidate?, '(send $array :* $str)' def on_send(node)
join_candidate?(node) { add_offense(node, location: :selector) } end
RuboCop Today
Started out with no configuration at all…
Today things are infinitely configurable
Metrics/LineLength: Enabled: false
Metrics/LineLength: Max: 100
Style/StringLiterals: Enabled: false
Style/StringLiterals: EnforcedStyle: double_quotes
You can set a target Ruby/Rails version
You can limit cops to certain folders with Exclude/Include directives
You can have different settings for the same cops in
different directories
You can inherit between configuration files
You can auto-generate an initial configuration for your project
rubocop —-auto-gen-config
And you can read about all of this in RuboCop’s
manual…
rubocop.readthedocs.io
gry is a smarter alternative to the built-in command https://github.com/pocke/gry
RuboCop started as a code style checker
•Style •Lint •Layout •Naming •Security •Performance •Performance •Rails •Bundler •Metric
•Gemspec
RuboCop is a great code formatter
rubocop —-only Layout -a
RuboCop does some linting better than ruby -w
rubocop —-lint
You can extend RuboCop with your own cops
Granite (business actions architecture for Rails applications) https://toptal.github.io/granite/
$ bundle exec rake new_cop[Department/Name]
https://rubocop.readthedocs.io/ en/latest/development/
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
RuboCop has a rich ecosystem of extensions
None
None
189!!!
Notable Extensions • rubocop-rspec • guard-rubocop • rubocop-sequel • rubocop-cask
Integration with code quality services •Code Climate •HoundCI •SideCI •Codacy
RuboCop has integrations with many editors and IDEs
Emacs 26.1 is out and it’s amazing!
(spacemacs)
The Road to RuboCop 1.0
#1 question I get asked about RuboCop?
When is RuboCop 1.0 coming?
Remove Rails (and maybe Performance) cops from RuboCop’s core
Provide a proper (and stable) API for writing RuboCop extensions
Introducing the brand new RuboCop HQ!
https://github.com/bbatsov/rubocop
https://github.com/rubocop-hq/rubocop
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)
Review the config of all cops and come up with
the best defaults
Ideally each default should be backed by solid data/rationale
Adjust the list of enabled by default cops
Come up with a less painful process for dealing with
new cops and configuration changes
mry makes RuboCop upgrades less painful https://github.com/pocke/mry
Agree on what’s going to be constituting breaking changes down
the road
Breaking changes •Cop API changes •Extension API changes •Dropping support
for Ruby versions •Renaming/removing cops •Renaming/changing/removing config values
Cop status “New” in minor releases
Cop status gets changed to Enabled/Disabled in major releases
Extra Cop metadata •Version added •Version default config changed •Version
deprecated
eslint.org-grade manual/website
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
None
That’s a lot of work!
Apes Together Strong!
Rubyists Together Strong!
Felina
Thanks! twitter: @bbatsov github: @bbatsov http//batsov.com http://emacsredux.com RubyKaigi Sendai, Japan
31.05.2018