Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
RuboCop Under a Microscope
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Koichi ITO
November 18, 2022
Programming
3.1k
11
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RuboCop Under a Microscope
Lint Night #1
https://lintnight.connpass.com/event/263931/
Koichi ITO
November 18, 2022
More Decks by Koichi ITO
See All by Koichi ITO
The Rails Doctrine Decade
koic
2
480
Reframing the Agile Manifesto
koic
5
4.7k
The NotImplementedError Problem in Ruby
koic
1
2.1k
Exploring RuboCop with MCP
koic
0
7.8k
Ruby and LLM Ecosystem 2nd
koic
1
2.3k
STYLE
koic
1
2.2k
Ruby and LLM Ecosystem
koic
3
14k
Write Code Every Day
koic
1
2.7k
Bliki (ja), and the Cathedral, and the Bazaar
koic
7
3.3k
Other Decks in Programming
See All in Programming
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Rails World 2026, Austin, Texas
marcoroth
0
170
残高管理から台帳サービスへの進化
artoy
0
120
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.1k
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
20
21k
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
230
SREの越境 / SRE Collaboration
y0hgi
2
300
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
4.9k
Jetpack Compose Mechanisms
skydoves
2
230
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
480
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
550
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
170
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
350
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
3.2k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The SEO identity crisis: Don't let AI make you average
varn
0
570
The Pragmatic Product Professional
lauravandoore
37
7.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
RailsConf 2023
tenderlove
30
1.6k
Writing Fast Ruby
sferik
630
63k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
300
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
2k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
350
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
540
Transcript
ҏ౻ߒҰ&4. *OD Lint Night #1 3VCP$PQͷ͘͠Έ RuboCop Under a Microscope
% ruby -v ruby 3.2.0dev % rubocop -v 1.39.0
@koic w044ϓϩάϥϚʔ w3VCP$PQίΞνʔϜ wגࣜձࣾӬγεςϜϚωδϝϯτ &4. *OD ΤϯδχΞϦϯάϚωʔδϟʔ݉ σΟεςΟϯάΠογϡυΤϯδχΞ
None
044ίϛϡχςΟͱͷڞੜΛࢧԉ 3BJMT044ύονձ #esm_oss
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .PSFUIBODPOUSJCVUPST
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .PSFUIBODPOUSJCVUPST "VUIPS
5IFpSTUDPNNJU % git log -p --reverse commit afbead34db54506c12a21dbd4ce04fada0f8b9a4 Author: Bozhidar
Batsov <
[email protected]
> Date: Sat Apr 21 13:06:42 2012 +0300 Initial commit to rubocop. --- .document | 5 +++++ .gitignore | 49 +++++++++++++++++++++++++++++++++++++++ ++++++++++ .rspec | 1 + Gemfile | 16 ++++++++++++++++ LICENSE.txt | 20 ++++++++++++++++++++ README.rdoc | 19 +++++++++++++++++++ Rakefile | 45 +++++++++++++++++++++++++++++++++++++++ ++++++ features/rubocop.feature | 9 +++++++++ features/step_definitions/rubocop_steps.rb | 0 features/support/env.rb | 13 +++++++++++++
5IFpSTUDPNNJU % git log -p --reverse commit afbead34db54506c12a21dbd4ce04fada0f8b9a4 Author: Bozhidar
Batsov <
[email protected]
> Date: Sat Apr 21 13:06:42 2012 +0300 Initial commit to rubocop. --- .document | 5 +++++ .gitignore | 49 +++++++++++++++++++++++++++++++++++++++ ++++++++++ .rspec | 1 + Gemfile | 16 ++++++++++++++++ LICENSE.txt | 20 ++++++++++++++++++++ README.rdoc | 19 +++++++++++++++++++ Rakefile | 45 +++++++++++++++++++++++++++++++++++++++ ++++++ features/rubocop.feature | 9 +++++++++ features/step_definitions/rubocop_steps.rb | 0 features/support/env.rb | 13 +++++++++++++ 👈
UI"OOJWFSTBSZZFBS🎉
3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .PSFUIBODPOUSJCVUPSTJOZFBST .F
None
.BJOUBJO3VCP$PQ)2&WFSZ%BZ IUUQTHJUIVCDPNLPJD PSHSVCPDPQ
.F
࣍ ߏจղੳͷ͘͠Έ ੩తղੳͷ͘͠Έલฤ ੩తղੳͷ͘͠Έޙฤ
੩తղੳͷུ֓ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ
ߏจղੳͷ͘͠Έ
ࣈ۟ղੳͱߏจղੳ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ
w 3VCZͷίʔυΛύʔε͢Δ3VCZύʔαʔ w 3VCZຊମͷύʔαʔͱҟͳΔ w 3VCP$PQҎ֎Ͱ0QBM 3VCZ/FYUͳͲͰར ༻͞Ε͍ͯΔ w 3VCP$PQ1BSTFSHFNʹΑΔߏจղੳʹ
ґଘ͢Δ 1BSTFSHFN
w 3VCZຊମ͕ߏจఆ͍ٛͯ͠ΔQBSTFZͷมߋ Λ͍ͬͯΔ ͍ΘΏΔSEύʔςΟ w 3VCZຊମͰ৽͍͠ߏจՃ͕͋ͬͯ 1BSTFSHFNଆͷߏจఆٛʹಉ༷ͷύονΛ खΛೖΕͳ͍ͱɺ৽͍͠ߏจΛղੳͰ͖ͳ͍ w
ݱࡏ0QBMίϛολʔ͕Ϧʔυ͍ͯ͠Δ 3VCZߏจղੳͷ࣮ͷͻͱͭ
ߏจղੳͱͦͷઌ ੩తղੳ 3VCP$PQ 1PMZpMM 3VCZ/FYU τϥϯεύΠϥ 0QBM ߏจղੳ 1BSTFS 3VCZίʔυ
"45 ݹ͍ϥϯλΠϜ 3VCZίʔυ +BWB4DSJQUίʔυ ੩తղੳޙͷमਖ਼ 3VCZίʔυ 1SPDFTTFE4PVSDF
w 1BSTFSHFNόʔδϣϯ͝ͱͷ3VCZߏจΛ #/' όοΧεɾφΞه๏ Ͱఆٛͯ͠Δ 3VCP$PQ1BSTFS͕ॲཧ͢Δߏจ ͷͪͷ෬ઢʹͳΓ·͢💡
w ίϩϯ ͷࠨลͷ୯ Ұͷه߸͕ӈลʹߏ ͞Ε͍ͯΔه߸ͷฒͼ Ͱஔ͞ΕΔ w 1BSTFSHFNͰ3BDD ͱ͍͏ύʔαδΣω
ϨʔλΛ͍ͬͯΔ Zͷ#/'αϯϓϧ
% cd ghq/github.com/whitequark/parser % bundle exec rake generate # Generate
the Ragel lexer and Racc parser (snip) % ls lib/parser/ all.rb macruby.rb ruby22.y ruby32.rb ast macruby.y ruby23.rb ruby32.y base.rb max_numparam_stack.rb ruby23.y rubymotion.rb builders messages.rb ruby24.rb rubymotion.y clobbering_error.rb meta.rb ruby24.y runner color.rb rewriter.rb ruby25.rb runner.rb context.rb ruby18.rb ruby25.y source current.rb ruby18.y ruby26.rb static_environment.rb current_arg_stack.rb ruby19.rb ruby26.y syntax_error.rb deprecation.rb ruby19.y ruby27.rb tree_rewriter.rb diagnostic ruby20.rb ruby27.y variables_stack.rb diagnostic.rb ruby20.y ruby30.rb version.rb lexer ruby21.rb ruby30.y lexer.rb ruby21.y ruby31.rb lexer.rl ruby22.rb ruby31.y Z͔Β SC͕ੜ͞ΕΔ
3VCZ͔Β1BSTFSͷҠ২ྫ
XIJUFRVBSLQBSTFS SVCZZ"MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO
DEdTSDHJUIVCDPNSVCZSVCZ HJUMPHQQBSTFZ DPNNJUEBGEDFBEBCBBGCBDDF "VUIPS,B[VLJ5TVKJNPUPLB[VLJ!DBMMDDOFU %BUF4VO.BS "MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO EJ⒎HJUBQBSTFZCQBSTFZ JOEFYDDGCG BQBSTFZ
CQBSTFZ !! !!Q@LXBSHTQ@LXBSH Q@LXSFTU \ OFX@IBTI@QBUUFSO@UBJM Q OFX@VOJRVF@LFZ@IBTI Q ! ! ^ 3VCZͷQBSTFZ
IUUQTHJUIVCDPNSVCZSVCZDPNNJUEBG
Trailing comma 3VCZͷߏจมߋ ΧϯϚ͕͋ͬͯͳͯ͘ྑ͘ͳΔ
key: value key: value, 3VCZͷQBSTFZ :BDD
3VCZ͔Β1BSTFSʹҠ২
3VCZDPEF Trailing comma 1BSTFSʹςετΛ͢
6TJOH3BDD key: value key: value, 1BSTFSͷ#/'Λߋ৽͢Δ
SVCZQBSTFW SVCZQBSTFCBTFEPOQBSTFSWFSTJPO SVCZQBSTFFDBTFQBUUFSOJO\B ^UIFOUSVF FOE DBTFNBUDI TFOEOJMQBUUFSO
JOQBUUFSO IBTIQBUUFSO QBJS TZNB JOU OJM USVF OJM SVCZQBSTFW SVCZQBSTFCBTFEPOQBSTFSWFSTJPO SVCZQBSTFFDBTFQBUUFSOJO\B^UIFOUSVF FOE DBTFNBUDI TFOEOJMQBUUFSO JOQBUUFSO IBTIQBUUFSO QBJS TZNB JOU OJM USVF OJM ߏจΤϥʔʹͳΒͣॲཧͰ͖Δ ΧϯϚ͕͋ͬͯͳͯ͘"45ಉ͡
w ৽͍͠3VCZ͕ग़ͯ1BSTFSHFN͕ରԠͯ͠ ͍ͳ͚Εɺ3VCP$PQ৽͍͠ߏจΛղੳ Ͱ͖ͳ͍ w 1BSTFSHFN3VCZ͕ϦϦʔε͞ΕΔࠒʹ ֓Ͷͷߏจ͕αϙʔτͰ͖͍ͯΔ w 3VCZͷແ໊ՄมҾͳͲରԠࡁΈ 1BSTFSHFN
w 1BSTFSHFNύʔαδΣωϨʔλ ʹ3BDDΛ͍ͬͯΔ w #/' όοΧεɾφΞه๏ Ͱ ॻ͔Ε͍ͯΔ w 3BDDΛͬͨߏจղੳ͍ͭͯ
ʰຊແಓฤʱͳͲࢀরͷ͜ͱ ߏจղੳೖ
੩తղੳͷ͘͠Έલฤ
੩తղੳ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ
֦ுϧʔϧ(FN ϥϯλΠϜͱίΞϧʔϧ 5SBWFSTBMϊʔυ֦ு 3VCZͷߏจղੳ 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF 3VCP$PQ 34QFD 3VCP$PQ
1FSGPSNBODF 3VCP$PQ 3BJMT 3VCP$PQͷґଘελοΫ
w Ϣʔβʔ͕ૢ࡞͢Δͷͱ͍͏ΑΓɺ 3FFL$-*πʔϧͳΜ͔Ͱ3VCP$PQͷϊʔ υύλʔϯͳͲͷػೳͷΈ͍͍ͨཁ͕ ͋ͬͯΓग़͞Εͨ w 5SBWFSTBM 1SPDFTTFE4PVSDF ϊʔυͷύ λʔϯهड़
"45֦ுϊʔυ"1*Λఏڙ͢Δ 3VCP$PQ"45
w 3VCZͷίʔυΛࢦఆ͞Εͨ3VCZόʔδϣϯ ʹج͍ͮͯղੳ͞Εͨ 3VCP$PQ"451SPDFTTFE4PVSDF w 1SPDFTTFE4PVSDFBTUͰ"45ΛऔಘՄೳ w "45ͷϊʔυछผʹԠͨ͡ίʔϧόοΫΛݺ ͼग़͢3VCP$PQ"455SBWFSTBM "45Λॲཧ͢Δ͘͠Έ
puts "hello" IFMMP αϯϓϧ
require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) 3VCP$PQ"451SPDFTTFE4PVSDF
require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) 3VCP$PQ"451SPDFTTFE4PVSDF w ྫ͑"45ιʔείϝϯτΛදݱͤͣɺ
ॲཧ͍ͯ͠ΔιʔείʔυͦͷͷͷใΛ ද͢ͷ͕1SPDFTTFE4PVSDFΦϒδΣΫτͰ͢ w 1SPDFTTFE4PVSDFޙड़͢Δ$PQ ϧʔϧ࣮ ͔ΒΞΫηεՄೳͳΦϒδΣΫτͰ͢
require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) ୈҾͷҙຯ
"451SPDFTTFE4PVSDFQBSTFS@DMBTT w 3VCZͷόʔδϣϯ͝ͱͷ ߏจղੳ͕༻ҙ͞Ε͍ͯΔ 1BSTFSHFNͷ"1*બఆ͢Δ w Ͳͷ3VCZόʔδϣϯͷߏจ ΛղੳΛ͢Δ͔ܾΊΔҾ ʹͳ͍ͬͯΔ
require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) 3VCP$PQ"451SPDFTTFE4PVSDF
require 'rubocop-ast' ast = RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ).ast #=>s(:send,
nil, :puts, s(:str, "hello")) ast.class 3VCP$PQ"451SPDFTTFE4PVSDFBTU
require 'rubocop-ast' ast = RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ).ast #=>s(:send,
nil, :puts, s(:str, "hello")) ast.class #=> RuboCop::AST::SendNode ast.class <= RuboCop::AST::Node # true 3VCP$PQ"454FOE/PEF
w 1BSTFSఏڙͷ/PEF Λܧঝͨ͠ศར"1* w 3VCP$PQ"45ͷ શϊʔυ͕ܧঝ͢Δ εʔύʔΫϥε w 3VCP$PQϧʔϧ࣮ ͷࡍʹʑࢀর͢Δ
IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEFSC 3VCP$PQ"45/PEF
ast.class #=> RuboCop::AST::SendNode ast.source #=> "puts \"hello\"" ast.location.line #=> 1
ast.loc.line #=> 1 ast.loc.column #=> 0 ast.loc.last_column #=> 12 ast.loc.source_range #=> ast.method_name #=> :puts ast.first_argument.basic_literal? #=> true 3VCP$PQ"454FOE/PEF
3VCP$PQ"455SBWFSTBM require 'rubocop-ast' include RuboCop::AST::Traversal # Event handler for `send`
node def on_send(node) puts node.source end walk(ast) #=> puts "hello"
3VCP$PQ"455SBWFSTBM require 'rubocop-ast' include RuboCop::AST::Traversal # Event handler for `send`
node def on_send(node) puts node.source end walk(ast) XBML BTU ຊฤͰͷݤͰ͢💡
w "45ͷύλʔϯϚον Λ͢ΔϛχϚϜݴޠ w Ϛονͨ͠ΛΩϟϓ νϟ͢Δ͜ͱ͕Ͱ͖Δ w EFG@OPEF@NBUDIFS ͳͲͷҾʹΘΕΔ IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEF@QBUUFSOSC
3VCP$PQ"45/PEF1BUUFSO
੩తղੳͷ͘͠Έޙฤ
w ղੳରͷ3VCZίʔυͷೖྗͱղੳ݁Ռͷ Ϩϙʔτग़ྗ w 3VCP$PQͷϧʔϧ࣮ͳΒͼʹ֦ு"1*ఏڙ w ϢʔβʔͷΧελϜઃఆɺΦϓγϣϯͷղऍ w σϑΥϧτϧʔϧSVCZTUZMFHVJEFʹ४ͣΔ 3VCP$PQ
3VCP$PQઃܭུ֓ 3VOOFS 5FBN 3FHJTUSZ $PQ#BTF NPCJMJ[F DPQ@DMBTTFT %FQU$VTUPN$PQ OFX DPEF
SVCZ@WFSTJPO OFX FOBCMFE $PNNJTTJPOFS JOWFTUJHBUF QSPDFTTFE@TPVSDF "455SBWFSTBM XBML BTU NJYJO JOWFTUJHBUF QSPDFTTFE@TPVSDF "45 1SPDFTTFE4PVSDF OFX OFX DPQT PO@YYY DBMMCBDL EFMFHBUFNFUIPET
3VCP$PQઃܭུ֓ 3VOOFS 5FBN 3FHJTUSZ $PQ#BTF NPCJMJ[F DPQ@DMBTTFT %FQU$VTUPN$PQ OFX DPEF
SVCZ@WFSTJPO OFX FOBCMFE $PNNJTTJPOFS JOWFTUJHBUF QSPDFTTFE@TPVSDF "455SBWFSTBM XBML BTU NJYJO JOWFTUJHBUF QSPDFTTFE@TPVSDF "45 1SPDFTTFE4PVSDF OFX OFX DPQT ৭ͳ͠3VCP$PQϥϯλΠϜ 3VCP$PQ"45 ϧʔϧ֦ுϙΠϯτ PO@YYY DBMMCBDL EFMFHBUFNFUIPET
wSVCPDPQίϚϯυͷϞδϡʔϧͰ͋ Δ$-*Ϟδϡʔϧ͔Βݺͼग़͞ΕΔ wݕࠪରͷϑΝΠϧύεΛݩʹղੳ ͱϧʔϧΛద༻͢Δ෦Ϟδϡʔϧ ܈Λ૬ޓ࡞༻ͤ͞Δ࣮ߦى 3VOOFS
wϧʔϧΛ࣮ͨ͠$PQ͕ొ͞Ε͍ͯ ΔΫϥε w📝$PQ#BTFͷ$MBTTJOIFSJUFE࣮ ʹΑͬͯɺͯ͢ͷ$PQ3FHJTUSZʹ ొ͞Ε͍ͯΔ ͬͱ͍ܰͨ͘͠ 3FHJTUSZ
wಈһ NPCJMJ[F ͞Εͨ$PQΛߏ ͢ΔΫϥε👮👮👮👮👮 wΧελϚΠζ͞ΕͨϧʔϧʹԠ͡ ͨνʔϜ͕·ΕΔ 5FBN
IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCNBTUFSMJCSVCPDPQDPQUFBNSC 5FBN ಈһ ༗ޮԽ͞ΕͨϧʔϧͰ͋Δ$PQͷ ΫϥεΛ3FHJTUSZ͔Βऔಘͯ͠ Πϯελϯεੜͯ͠ฦ͠·͢ɻ 🚨
IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCNBTUFSMJCSVCPDPQDPQUFBNSC 5FBN ௐࠪ ద༻͢Δ$PQͰߏ͢Δ νʔϜͱߏจղੳͯ͠Δ 1SPDFTTFE4PVSDFΛݩ ʹ$PNNJTTJPOFSΛݺͿ 🚨 🔎
w੩తղੳΛऔΓΔॺ👮 wಈһ͞Εͨ$PQͨͪ 5FBN ʹΑͬͯ ༰ٙऀ ίʔυ Λݕࠪ͢Δ wͦͷਖ਼ମ"455SBWFSTBMΛNJYJOͨ͠ ΫϥεɻॺࣗΒͰࠪ͢Δ XBML
$PNNJTTJPOFS
$PNNJTTJPOFS ϝλ ⭐ XBMLͰݺͼग़͞ΕΔίʔϧόοΫ ϝιουΛϝλϓϩάϥϛϯάͰ ఆ͍ٛͯ͠Δ IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCWMJCSVCPDPQDPQDPNNJTTJPOFSSC
$PNNJTTJPOFS XBML ⭐ JOWFTUJHBUFʹ͞Εͨ 1SPDFTTFE4PVSDFΛͱʹ͠ ͨ"45ΛҾʹXBMLϝιου ΛݺͿ XBML͔ΒίʔϧόοΫ͞Εͨ PO@YYYϝιουͱಉ໊Ͱ$PQʹ ఆٛ͞Ε͍ͯΔPO@YYYʹҠৡ͢Δ
IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCWMJCSVCPDPQDPQDPNNJTTJPOFSSC 🔎
3VCP$PQઃܭུ֓ ࠶ܝ 3VOOFS 5FBN 3FHJTUSZ $PQ#BTF NPCJMJ[F DPQ@DMBTTFT %FQU$VTUPN$PQ OFX
DPEF SVCZ@WFSTJPO OFX FOBCMFE $PNNJTTJPOFS JOWFTUJHBUF QSPDFTTFE@TPVSDF "455SBWFSTBM XBML BTU NJYJO JOWFTUJHBUF QSPDFTTFE@TPVSDF "45 1SPDFTTFE4PVSDF OFX OFX DPQT ৭ͳ͠3VCP$PQϥϯλΠϜ 3VCP$PQ"45 ϧʔϧ֦ுϙΠϯτ PO@YYY DBMMCBDL EFMFHBUFNFUIPET
w$PQͷεʔύΫϥε👮 wϧʔϧΛ࣮͢Δͯ͢ͷ$PQ $PQ#BTFΛܧঝ͢Δ w📝$PQ$PQݹ͍ඇਪͷεʔύʔΫϥ εͳͷͰɺ$PQ#BTFʹߋ৽͠·͠ΐ͏ $PQ#BTF
w$PQ#BTFΛܧঝ࣮͠ࡍͷϧʔϧΛ࣮ͨ͠ $PQ👮 w$PQඞͣԿΒ͔ͷ෦ॺʹॴଐ͢Δ wFH4UZMF4USJOH-JUFSBMTDPQ wΈࠐΈ$PQͱࣗ࡞$PQͰ࣮ͷҧ͍ͳ͍ ΧελϜ$PQ %FQU$VTUPN$PQ
module Cop module Style class MixinUsage < Base MSG =
'`%<statement>s` is used at the top level.' \ 'Use inside `class` or `module`.'.freeze RESTRICT_ON_SEND = %i[include extend prepend].freeze def_node_matcher :include_statement, <<~PATTERN (send nil? ${:include :extend :prepend} const) PATTERN def on_send(node) return unless (statement = include_statement(node)) return unless top_level_node?(node) add_offense(node, message: format(MSG, statement: statement)) end $PQ ϧʔϧ ͷ࣮ྫ
ϧʔϧ࣮ͷৄࡉެࣜจॻ IUUQTEPDTSVCPDPQPSHSVCPDPQEFWFMPQNFOUIUNM
࣮ࣄྫ3VCZ,BJHJಈը IUUQTSVCZLBJHJPSHQSFTFOUBUJPOTLPJDIUNMKVO
" ;ͨͭͷόʔδϣϯ
w3VCP$PQͰɺ3VCZҎ্ͷ੩తղੳ͕ɺ 3VCZҎ্ͷϥϯλΠϜͰՄೳ wϥϯλΠϜཁٻͷ3VCZͷόʔδϣϯ3VCP$PQࣗମͷ ίʔυ͕ॻ͔ΕͯΔ3VCZόʔδϣϯͰ͋Γ3VCZຊମ͕ ղੳධՁ͢Δ w੩తղੳͷίʔυ1BSTFSHFNͰղੳ͢Δ wSVCPDPQZNMͷ5BSHFU3VCZ7FSTJPOͰWFSTJPOࢦఆՄ ղੳόʔδϣϯͱ࣮ߦόʔδϣϯ
4VQQPSUNBUSJY W
❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ "OBMZTJT3VCZWFSTJPOT TargetRubyVersionJOSVCPDPQZNM 3VOUJNF3VCZWFSTJPOT ruby -v
3VCZͰ3VCZΛղੳ͢Δ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ 3VCZॲཧܥͷղੳධՁ
3BDDʹΑΔߏจղੳ
lίʔυΛখઆͷΑ͏ʹಡΜͰɺ ಠతͳےॻ͖ࢥ͍ΑΒ͵ن ଇੑΛָ͠Έ·͠ΐ͏ɻҰݟඇৗ ʹෳࡶͳͷΛίϯύΫτͰΤϨ ΨϯτͳߏͰ࣮ݱ͍ͯ͠Δͷ Λݟ͚ͭΔ͜ͱ͋Εɺখઆͳ ͕ΒوॏͳๅੴͷΑ͏ͳίʔυΛ ݟ͚ͭΔ͜ͱ͋Γ·͢ɻz $PEF3FBEJOH