Road to RuboCop 1.0

023b04c98f39cc041293d780352432ff?s=47 Koichi ITO
September 04, 2020

Road to RuboCop 1.0

RubyKaigi Takeout 2020 Day1

023b04c98f39cc041293d780352432ff?s=128

Koichi ITO

September 04, 2020
Tweet

Transcript

  1. Road to RuboCop 1.0 ,PJDIJ*50&4. *OD 3VCZ,BJHJ5BLFPVU Ride on RuboCop

    1.0 for safe static analysis
  2. !LPJD w 3VCP$PQDPSFUFBN w 044QSPHSBNNFS w 5FDITQFBLFS w %JTUJOHVJTIFE&OHJOFFSBU &4.

    *OD
  3. &4. *OD

  4. Support OSS community

  5. None
  6. #VOEMFS 1SZ 34QFD 3VCP$PQ CZFCVH 3VCZ,BJHJ %3&$0.CPPUI

  7. None
  8. 3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .PSFUIBODPOUSJCVUPSTJOZFBST

  9. 3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 "VUIPS .PSFUIBODPOUSJCVUPSTJOZFBST

  10. 3VCP$PQDPSFEFWFMPQFST +0900 UTC+0200 +0300 +0800 -0400 .F .PSFUIBODPOUSJCVUPSTJOZFBST

  11. 3VCP$PQ"SDIJUFDUVSF

  12. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ"45QBSTFS 3VCP$PQ"SDIJUFDUVSF  1BSTFSHFN 3VCP$PQ"45

    3VCP$PQDPSF 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  13. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ"45QBSTFS $VTUPN$PQT 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  14. $PQTHFNJpFE CZ3VCP$PQ)2

  15. 3VCP$PQDPSF 1BTU"SDIJUFDUVSF  1BSTFSHFN 3VCP$PQ 34QFD

  16. (FNJpFEDPQT

  17. SVCPDPQIRSVCPDPQ &YUSBDU1FSGPSNBODF$PQTJOUPBTFQBSBUFHFN

  18. None
  19. 3VCP$PQDPSF 'JSTUFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF &YUSBDUFE

  20. None
  21. None
  22. +VBOJUP'BUBTGBTUSVCZSFQP

  23. SBJMTSBJMT

  24. #FODINBSLJQT require 'benchmark/ips' SLUG = 'writing-fast-ruby' def slow SLUG.gsub('-', '

    ') end def fast SLUG.tr('-', ' ') end Benchmark.ips do |x| x.report('String#gsub') { slow } x.report('String#tr') { fast } x.compare! end % ruby -v gsub-vs-tr.rb ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin17] Warming up -------------------------------------- String#gsub 59.463k i/100ms String#tr 296.069k i/100ms Calculating ------------------------------------- String#gsub 598.537k (± 1.8%) i/s - 3.033M in 5.068466s String#tr 2.955M (± 0.9%) i/s - 14.803M in 5.009464s Comparison: String#tr: 2955357.8 i/s String#gsub: 598537.4 i/s - 4.94x (± 0.00) slower
  25. w 3VCP$PQDPSFGPDVTPOQMBUGPSN JOEFQFOEFOU3VCZQFSGPSNBODF w 1FSGPSNBODFDPQGPDVTPO.3*`T QFSGPSNBODF w 5IFpSTUFYUSBDUFEHFN 3VCP$PQ (FNJGZOPUFT

  26. w'JSTU `cp`DPNNBOEUPDPQZ GSPNUIFQFSGPSNBODFDPQ pMFTUPUIFOFXSFQPTJUPSZ w*UTFBTZ CVUJUSFNPWFTGit IJTUPSZ )PXXPVMEZPVHFNJGZ

  27. w.BJOUBJOFSTXBOUUPUSBDF UIFSFBTPOGPSDIBOHFT GSPNUIFDIBOHFIJTUPSZ w*XPVMEMJLFUPLFFQ DPOUSJCVUPSOBNF (JUIJTUPSZJTNBUUFS

  28. w*BTLFE!BNBUTVEB IPX,BNJOBSJEJWJEFE SFOEFSJOHFOHJOFT )PXXBTUIFSFQPTJUPSZLFQUIJTUPSZ

  29. l *VTFEHJUDIFSSZQJDL XIFO*HBNJpFE,BNJOBSJ⚡ !BNBUTVEB

  30. MPDBM SFNPUF(JU)VC 3VCP$PQ1FSGPSNBODF 1VMMOFXSFQP 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF #BTFEPO 3VCP$PQ34QFD TUSVDUVSF %

    git remote add upstream-performance \ <rubocop-performance URL> % git pull upstream-performance
  31. MPDBM SFNPUF(JU)VC 3VCP$PQ1FSGPSNBODF 'FUDIPSJHJOBMSFQP 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF % git remote add

    upstream-core \ <rubocop URL> % git fetch upstream-core
  32. MPDBM SFNPUF(JU)VC 3FQFBUDIFSSZQJDLT 3VCP$PQ1FSGPSNBODF .BOZNBOZ HJUDIFSSZQJDL 3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF % git

    cherry-pick 7cbfa5a <hash of core> % git cherry-pick 7cbfa5a % git cherry-pick ...
  33. MPDBM # DONE! % git push origin master SFNPUF(JU)VC 1VTIOFXSFQP

    3VCP$PQ1FSGPSNBODF 3VCP$PQ$PSF 3VCP$PQ1FSGPSNBODF
  34. wPWFSDIFSSZQJDLT )PXNBOZDIFSSZQJDLT % git log --oneline lib/rubocop/cop/performance \ spec/rubocop/cop/performance |

    wc -l 225 % git log --oneline lib/rubocop/cop/rails \ spec/rubocop/cop/rails | wc -l 315 *NOPUTVSFJUJTUIFCFTUPQUJPO
  35. SVCPDPQIRSVCPDPQ &YUSBDU3BJMT$PQTJOBTFQBSBUF

  36. None
  37. 3VCP$PQDPSF 4FDPOEFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT &YUSBDUFE

  38. None
  39. w 3VCP$PQDPSFXJMMOPUTVQQPSU GSBNFXPSLTQFDJpDDPQT w 3VCP$PQ3BJMTOPXEFQFOETPO3BDL HFN w 5IFTFDPOEFYUSBDUFEHFN 3VCP$PQ 

    w 5IF3VCP$PQ3BJMTWFSTJPOJT (FNJGZOPUFT
  40. lSVCPDPQSBJMTz FYJTUFEUP HFNJGZ SVCPDPQZNMJO SBJMTSBJMTSFQP /BNFTQBDFQSPCMFN 3VCP$PQ3BJMTW

  41. None
  42. w3VCP$PQ3BJMTWNJHSBUFE UPSVCPDPQSBJMT@DPOpHHFN w3VCP$PQ3BJMTWFYUSBDUFE 3BJMTDPQTGSPN3VCP$PQ DPSF 3VCP$PQ3BJMTWBOEW

  43. w3VCP$PQ3BJMTXJMMESPQ 3BJMTTVQQPSU w3VCP$PQ3BJMTXJMMOPU BDDFQUDPQTGPSPMEFS3BJMT 3VCP$PQ3BJMTQMBOOFEDIBOHFT

  44. 3VCP$PQDPSF $VTUPN$PQT 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF $VTUPN$PQ

  45. None
  46. w(FOFSBUFTEJSFDUPSZ TUSVDUVSFGPSZPVSHFN w$POUBJOTNPOLFZQBUDI DPEF #BELOPXIPX SVCPDPQFYUFOTJPOHFOFSBUPS

  47. .POLFZQBUDIPO 3VCP$PQDPSF

  48. w:PVDBODSFBUFBOFXSEQBSUZ 3VCP$PQHFNUPTVQQPSUMJCSBSZ TQFDJpD ZPVSQSPKFDU SFRVJSFNFOUT FUD w:PVDBOIBOEMFEPNBJO LOPXMFEHF 8IFOEPZPVDSFBUFBSEQBSUZHFN

  49. SVCPDPQIRSVCPDPQSBJMT "EEOFXA3BJMT/FX(MPCBM.PEFMADPQ

  50. 1SPQPTBMTGPS &OGPSDF3BJMT&OHJOF

  51. 3VCP$PQ3BJMTUBSHFUTl3BJMTXBZz

  52. IUUQTqFYQPSUFOHJOFFSJOHJTPMBUJOHSBJMTFOHJOFTXJUISVCPDPQGFBCB

  53. 3VCP$PQ"1*W

  54. SVCPDPQIRSVCPDPQ *NQSPWJOHBVUPDPSSFDUJPOT"1*

  55. < Base FYUFOE"VUP$PSSFDUPS EPcDPSSFDUPSc

  56. w0ME"1*TXJMMOPUCFSFNPWFE TPPO CVU`Cop::Base`JT TUSPOHMZSFDPNNFOEFEOPX w4FFl6QHSBEF/PUFTzGPS EFUBJMT &YUFOTJPO"1*DIBOHFEGPSW

  57. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQ"45 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  58. SVCPDPQIRSVCPDPQ 6TJOHSVCPDPQBTU

  59. 3VCP$PQDPSF 1BTU"SDIJUFDUVSF W 1BSTFSHFN 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT

  60. 5IJSEFYUSBDUFEHFN 1BSTFSHFN 3VCP$PQ"45 3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT 3VCP$PQDPSF

    &YUSBDUFE
  61. None
  62. w*OUFOEFEOPUGPS3VCP$PQ VTFSTEJSFDUMZ w3FFL B$-*UPPMXBOUUPVTF OPEFQBUUFSOTJOEFQFOEFOUMZ GSPN3VCP$PQDPSF 3VCP$PQ"45

  63. USPFTTOFSSFFL SVCPDPQ

  64. 3VCP$PQ"45/PEF1BUUFSO w &YUFOEFETZOUBYGPS FYQSFTTJOHOPEFT w 1BUUFSONBUDIJOHUP DBQUVSFNBUDIJOH WBMVFT w 0GUFOVTFEBTBO

    BSHVNFOUPG def_node_matcher FUD IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEF@QBUUFSOSC
  65. 3VCP$PQ"45/PEF w *OIFSJUT1BSTFS BOEQSPWJEFT QSFEJDBUF NFUIPET w :PVDBOSFGFS 3VCP$PQ JNQMFNFOUBUJPOT

    IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEFSC
  66. 3VCP$PQ"451SPDFTTFE4PVSDF require 'rubocop-ast' ast = RuboCop::AST::ProcessedSource.new( 'puts "hello"', 2.7 ).ast

    #=>s(:send, nil, :puts, s(:str, "hello")) ast.class #=> RuboCop::AST::SendNode ast.send_type? #=> true ast.first_argument.basic_literal? #=> true
  67. 3VCP$PQ"455SBWFSTBM require 'rubocop-ast' include RuboCop::AST::Traversal # Event handler for `send`

    node def on_send(node) 'hi' end walk(ast) #=> hi
  68. w4VQQPSUTTUBUJDBOBMZTJTCZ QBSTJOH QBUUFSONBUDIJOH  BOEFWFOUIBOEMJOH w3VCP$PQJTUIF3FGFSFODF *NQMFNFOUBUJPO 3VCP$PQ"45JTBIBSWFTUFEMJCSBSZ

  69. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 1BSTFS 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  70. $PEFPG6OEFSXPSME

  71. 6OEFSUIF3VCP$PQ 1BSTFSHFN XIJUFRVBSLQBSTFS 3VCP$PQ"45 3VCP$PQ DPSF 0QBM 3VCZ/FYU :FU"OPUIFS "OBMZ[FS

    3BDD
  72. None
  73. w3VCZQBSTFSXSJUUFOJO3VCZ w4VQQPSUT.3* +3VCZ  5SVGqF3VCZ w#/'JTXSJUUFOCZ3BDD CBTFEPOQBSTFZPG3VCZ 8IBU`T1BSTFSHFN

  74. w/FX3VCZTZOUBYJOUSPEVDFEJO 1BSTFSBTFYQFSJNFOUBM w3VCP$PQ"45FYUFOET1BSTFS`T OFX"1* w$PQTDBOIBOEMFOFXTZOUBYUSFF OPEFT /FX3VCZTZOUBYDBOCFVTFEJO3VCP$PQ

  75. XIJUFRVBSLQBSTFS SVCZZ"MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO

  76. 8BUDIQBSTFZ 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  !  !  ^
  77. IUUQTHJUIVCDPNSVCZSVCZDPNNJUEBG

  78. 3VCZSFQPUFTUDPEF Trailing comma

  79. QBSTFZ :BDD key: value key: value,

  80. 1VMM3FRVFTU

  81. 1BSTFSHFNUFTUDPEF 3VCZDPEF Trailing comma

  82. #/'PG1BSTFSHFN 6TJOH3BDD key: value key: value,

  83. $PNQBSFUXPPVUQVUT 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 4BNF"45
  84. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS "SDIJUFDUVSFUPXBSET 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  85. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQ$PSF 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  86. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 3VCP$PQDPSFVQEBUF 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF

    3VCP$PQ 34QFD 3VCP$PQ 1FSGPSNBODF 3VCP$PQ 3BJMT
  87. 4BGFBOE 4BGF"VUP$PSSFDU

  88. SVCPDPQIRSVCPDPQ *NQMFNFOUPQUJPOTUPSVOPOMZTBGFDPQTBOE TBGFBVUPDPSSFDUT

  89. None
  90. w3VCP$PQJTBTUBUJDBOBMZTJTUPPM BOESVOUJNFJOGPJTOPUBWBJMBCMF w'BMTFQPTJUJWFEFUFDUJPONBZIBQQFO w*ODPNQBUJCMFBVUPDPSFSFDUJPONBZ IBQQFO 8IZVOTBGF

  91. &YBNQMFEFGBVMUZNM Lint/RaiseException: VersionAdded: 0.56 + Safe: false Style/DoubleNegation: VersionAdded: '0.19'

    VersionChanged: '0.84' + SafeAutoCorrect: false
  92. w*OEJDBUFTXIFUIFSUIFDPQ DBOZJFMEGBMTFQPTJUJWFT CZEFTJHO PSOPU 4BGF

  93. &YBNQMF7BSJBCMF DPOTUBOU UZQFT # Performance/AncestorsInclude # bad A.ancestors.include?(B) # good

    A <= B
  94. None
  95. w'BMTFQPTJUJWFGPS /PLPHJSJ9.-/PEFBODFTUPST w'SFRVFOUGBMTFQPTJUJWFTEVFUP UIFEJGGFSFODFCFUXFFO "DUJWF3FDPSEBOE1030JO3BJMT 6OTBGFBCPVUSFDFJWFSUZQF

  96. w*OEJDBUFTXIFUIFSUIFBVUPDPSSFDUB DPQEPFTJTTBGF FRVJWBMFOU CZ EFTJHO w*GSafe: falseJTTFU  UIFOSafeAutoCorrect: falseJTBMTPTFU

    4BGF"VUP$PSSFDU
  97. &YBNQMFAOJMAWBSJBCMF # Performance/StartWith cop # bad str =~ /\Aab/ #

    good str.start_with?('ab')
  98. w&SSPSJGUIFWBSJBCMFJTOJM w*UDBOCFBWPJEFECZBEEJOHB TBGFOBWJHBUJPOPQFSBUPS    CVUJUJTOPUBMXBZTSJHIU 6OTBGFBCPVUOJMWBSJBCMF

  99. &YBNQMFFYUFSOBMSFTPVSDFT # Rails/UniqBeforePluck cop # bad Model.pluck(:id).uniq # good Model.distinct.pluck(:id)

  100. None
  101. w$PNQBUJCJMJUZJTOPUHVBSBOUFFE CFUXFFO3VCZTuniqNFUIPE BOE3%#.`TDISTINCT w'PSFYBNQMF UIFEFGBVMU.Z42- DPMMBUJPOJTDBTFJOTFOTJUJWF 6OTBGFBCPVUFYUFSOBMSFTPVSDFT

  102. 3VCZ,BJHJDBODFMMFE

  103. 3VCPDPQ5ZQFE

  104. 803,*/130(3&44

  105. SVCPDPQIRSVCPDPQ $-*PQUJPOTDIBOHFBVUPDPSSFDUOPXTBGFCZEFGBVMU

  106. wTBGF wB BVUPDPSSFDU w" BVUPDPSSFDUBMM ASVCPDPQAPQUJPOTGPSTBGFVOTBGF

  107. w"QQMZPOMZTBGFBVUPDPSSFDUJPO wGTUSJOHMJUFSBMDPNNFOUJTOPU BVUPDPSSFDUFECZEFGBVMUBTJU XBTCFGPSF #3&",*/($)"/(&⚠ B BVUPDPSSFDU

  108. w"QQMZTBGFBOEVOTBGFBVUP DPSSFDUJPO w5IJTPQUJPOJTUIFTBNFABA CFIBWJPSPG3VCP$PQBOEMPXFS w-JLFAHJUCSBODIEAWTA%A " BVUPDPSSFDUBMM

  109. /FXDPQTUBUVT

  110. SVCPDPQIRSVCPDPQ .BLFJUQPTTJCMFUPFOBCMFEJTBCMFQFOEJOHDPQT

  111. None
  112. w/FXDPQTUBUVTTUBSUTXJUIQFOEJOH PSEJTBCMFE  w"MMQFOEJOHDPQTBSFFOBCMFEXIFO UIFNBKPSWFSTJPOCVNQT w1MFBTFHJWFGFFECBDLJGZPVIBWF JTTVFTBCPVUOFXDPQT /FXDPQTUBUVT

  113. 4VQQPSUQPMJDZ

  114. SVCPDPQIRSVCPDPQ 6QEBUFPCTPMFUFSVCJFTBOEBEEBEPDGPSDPNQBUJCJMJUZ

  115. w3VCP$PQXJMMQSPWJEFTVQQPSU &0-FE3VCZGPSBCPVUBZFBS w1MFBTFNJHSBUFUPOFX WFSTJPOPG3VCZ 4VQQPSUQPMJDZ

  116. None
  117. 0OFNPSFUIJOH

  118. $VTUPNDPQT 3VOUJNFFOHJOFBOE DPSFDPQT /PEFQBUUFSOBOE OPEFFYUFOTJPOT 3VCZ`T"45QBSTFS 1BSTFSHFN 3VCP$PQ"45 3VCP$PQDPSF 3VCP$PQ

    34QFD 3VCP$PQ 1FSGPSNBODF $POpHVSBUJPO SVCPDPQZNM #VJMUJODPQT
  119. EPDTSVCPDPQPSH

  120. )BQQZTPDJBMDPEJOH +0900 UTC+0200 +0300 +0800 -0400 XJUINBOZDPOUSJCVUPSTBOEZPV

  121. 3VCZ,BJHJNFNPSJBM