Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RuboCop Under a Microscope

Koichi ITO
November 18, 2022

RuboCop Under a Microscope

Koichi ITO

November 18, 2022
Tweet

More Decks by Koichi ITO

Other Decks in Programming

Transcript

  1. ҏ౻ߒҰ&4. *OD
    Lint Night #1
    3VCP$PQͷ͘͠Έ
    RuboCop Under a
    Microscope
    % ruby -v
    ruby 3.2.0dev
    % rubocop -v
    1.39.0

    View full-size slide

  2. @koic
    w044ϓϩάϥϚʔ
    w3VCP$PQίΞνʔϜ
    wגࣜձࣾӬ࿨γεςϜϚωδϝϯτ &4. *OD

    ΤϯδχΞϦϯάϚωʔδϟʔ݉
    σΟεςΟϯάΠογϡυΤϯδχΞ

    View full-size slide

  3. 044ίϛϡχςΟͱͷڞੜΛࢧԉ
    3BJMT044ύονձ
    #esm_oss

    View full-size slide

  4. 3VCP$PQDPSFEFWFMPQFST
    +0900
    UTC+0200 +0300 +0800 -0400
    .PSFUIBODPOUSJCVUPST

    View full-size slide

  5. 3VCP$PQDPSFEFWFMPQFST
    +0900
    UTC+0200 +0300 +0800 -0400
    .PSFUIBODPOUSJCVUPST
    "VUIPS

    View full-size slide

  6. 5IFpSTUDPNNJU
    % git log -p --reverse
    commit afbead34db54506c12a21dbd4ce04fada0f8b9a4
    Author: Bozhidar Batsov
    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 +++++++++++++

    View full-size slide

  7. 5IFpSTUDPNNJU
    % git log -p --reverse
    commit afbead34db54506c12a21dbd4ce04fada0f8b9a4
    Author: Bozhidar Batsov
    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 +++++++++++++
    👈

    View full-size slide

  8. UI"OOJWFSTBSZZFBS🎉

    View full-size slide

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

    View full-size slide

  10. .BJOUBJO3VCP$PQ)2&WFSZ%BZ
    IUUQTHJUIVCDPNLPJD PSHSVCPDPQ

    View full-size slide

  11. ໨࣍
    ߏจղੳͷ͘͠Έ
    ੩తղੳͷ͘͠Έલฤ
    ੩తղੳͷ͘͠Έޙฤ

    View full-size slide

  12. ੩తղੳͷུ֓
    ࣈ۟ղੳ ߏจղੳ ੩తղੳ
    Ϩϙʔτ
    ιʔείʔυ
    ೖྗ
    ॲཧ
    ग़ྗ

    View full-size slide


  13. ߏจղੳͷ͘͠Έ

    View full-size slide

  14. ࣈ۟ղੳͱߏจղੳ
    ࣈ۟ղੳ ߏจղੳ ੩తղੳ
    Ϩϙʔτ
    ιʔείʔυ
    ೖྗ
    ॲཧ
    ग़ྗ

    View full-size slide

  15. w 3VCZͷίʔυΛύʔε͢Δ3VCZ੡ύʔαʔ
    w 3VCZຊମͷύʔαʔͱ͸ҟͳΔ
    w 3VCP$PQҎ֎Ͱ͸0QBM 3VCZ/FYUͳͲͰར
    ༻͞Ε͍ͯΔ
    w 3VCP$PQ͸1BSTFSHFNʹΑΔߏจղੳʹ
    ґଘ͢Δ
    1BSTFSHFN

    View full-size slide

  16. w 3VCZຊମ͕ߏจఆ͍ٛͯ͠ΔQBSTFZͷมߋ
    Λ௥͍ͬͯΔ ͍ΘΏΔSEύʔςΟ੡඼

    w 3VCZຊମͰ৽͍͠ߏจ௥Ճ͕͋ͬͯ΋
    1BSTFSHFNଆͷߏจఆٛʹಉ༷ͷύονΛ
    खΛೖΕͳ͍ͱɺ৽͍͠ߏจΛղੳͰ͖ͳ͍
    w ݱࡏ0QBMίϛολʔ͕Ϧʔυ͍ͯ͠Δ
    3VCZߏจղੳͷ࣮૷ͷͻͱͭ

    View full-size slide

  17. ߏจղੳͱͦͷઌ
    ੩తղੳ
    3VCP$PQ
    1PMZpMM
    3VCZ/FYU
    τϥϯεύΠϥ
    0QBM
    ߏจղੳ
    1BSTFS
    3VCZίʔυ "45
    ݹ͍ϥϯλΠϜ
    3VCZίʔυ
    +BWB4DSJQUίʔυ
    ੩తղੳޙͷमਖ਼
    3VCZίʔυ
    1SPDFTTFE4PVSDF

    View full-size slide

  18. w 1BSTFSHFN͸όʔδϣϯ͝ͱͷ3VCZߏจΛ
    #/' όοΧεɾφ΢Ξه๏
    Ͱఆٛͯ͠Δ
    3VCP$PQ1BSTFS͕ॲཧ͢Δߏจ
    ͷͪͷ෬ઢʹͳΓ·͢💡

    View full-size slide

  19. w ίϩϯ
    ͷࠨลͷ୯
    Ұͷه߸͕ӈลʹߏ੒
    ͞Ε͍ͯΔه߸ͷฒͼ
    Ͱஔ׵͞ΕΔ
    w 1BSTFSHFNͰ͸3BDD
    ͱ͍͏ύʔαδΣω
    ϨʔλΛ࢖͍ͬͯΔ
    Zͷ#/'αϯϓϧ

    View full-size slide

  20. % 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͕ੜ੒͞ΕΔ

    View full-size slide

  21. 3VCZ͔Β1BSTFS΁ͷҠ২ྫ

    View full-size slide

  22. XIJUFRVBSLQBSTFS
    SVCZZ"MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO

    View full-size slide

  23. 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

    View full-size slide

  24. IUUQTHJUIVCDPNSVCZSVCZDPNNJUEBG

    View full-size slide

  25. Trailing comma
    3VCZͷߏจมߋ
    ΧϯϚ͕͋ͬͯ΋ͳͯ͘΋ྑ͘ͳΔ

    View full-size slide

  26. key: value
    key: value,
    3VCZͷQBSTFZ :BDD

    View full-size slide

  27. 3VCZ͔Β1BSTFSʹҠ২

    View full-size slide

  28. 3VCZDPEF
    Trailing comma
    1BSTFSʹςετΛ଍͢

    View full-size slide

  29. 6TJOH3BDD
    key: value
    key: value,
    1BSTFSͷ#/'Λߋ৽͢Δ

    View full-size slide

  30. 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͸ಉ͡

    View full-size slide

  31. w ৽͍͠3VCZ͕ग़ͯ΋1BSTFSHFN͕ରԠͯ͠
    ͍ͳ͚Ε͹ɺ3VCP$PQ͸৽͍͠ߏจΛղੳ
    Ͱ͖ͳ͍
    w 1BSTFSHFN͸3VCZ͕ϦϦʔε͞ΕΔࠒʹ͸
    ֓Ͷͷߏจ͕αϙʔτͰ͖͍ͯΔ
    w 3VCZͷແ໊Մม௕Ҿ਺ͳͲ΋ରԠࡁΈ
    1BSTFSHFN

    View full-size slide

  32. w 1BSTFSHFN͸ύʔαδΣωϨʔλ
    ʹ3BDDΛ࢖͍ͬͯΔ
    w #/' όοΧεɾφ΢Ξه๏
    Ͱ
    ॻ͔Ε͍ͯΔ
    w 3BDDΛ࢖ͬͨߏจղੳ͍ͭͯ͸
    ʰຊແಓฤʱͳͲࢀরͷ͜ͱ
    ߏจղੳೖ໳

    View full-size slide


  33. ੩తղੳͷ͘͠Έલฤ

    View full-size slide

  34. ੩తղੳ
    ࣈ۟ղੳ ߏจղੳ ੩తղੳ
    Ϩϙʔτ
    ιʔείʔυ
    ೖྗ
    ॲཧ
    ग़ྗ

    View full-size slide

  35. ֦ுϧʔϧ(FN
    ϥϯλΠϜͱίΞϧʔϧ
    5SBWFSTBM΍ϊʔυ֦ு
    3VCZͷߏจղੳ 1BSTFSHFN
    3VCP$PQ"45
    3VCP$PQDPSF
    3VCP$PQ
    34QFD
    3VCP$PQ
    1FSGPSNBODF
    3VCP$PQ
    3BJMT
    3VCP$PQͷґଘελοΫ

    View full-size slide

  36. w Ϣʔβʔ͕௚઀ૢ࡞͢Δ΋ͷͱ͍͏ΑΓ͸ɺ
    3FFL΍$-*πʔϧͳΜ͔Ͱ3VCP$PQͷϊʔ
    υύλʔϯͳͲͷػೳͷΈ࢖͍͍ͨཁ๬͕
    ͋ͬͯ੾Γग़͞Εͨ
    w 5SBWFSTBM 1SPDFTTFE4PVSDF ϊʔυͷύ
    λʔϯهड़ "45֦ுϊʔυ"1*Λఏڙ͢Δ
    3VCP$PQ"45

    View full-size slide

  37. w 3VCZͷίʔυΛࢦఆ͞Εͨ3VCZόʔδϣϯ
    ʹج͍ͮͯղੳ͞Εͨ
    3VCP$PQ"451SPDFTTFE4PVSDF
    w 1SPDFTTFE4PVSDFBTUͰ"45ΛऔಘՄೳ
    w "45ͷϊʔυछผʹԠͨ͡ίʔϧόοΫΛݺ
    ͼग़͢3VCP$PQ"455SBWFSTBM
    "45Λॲཧ͢Δ͘͠Έ

    View full-size slide

  38. puts "hello"
    IFMMP αϯϓϧ

    View full-size slide

  39. require 'rubocop-ast'
    RuboCop::AST::ProcessedSource.new(
    'puts "hello"', 3.1
    )
    3VCP$PQ"451SPDFTTFE4PVSDF

    View full-size slide

  40. require 'rubocop-ast'
    RuboCop::AST::ProcessedSource.new(
    'puts "hello"', 3.1
    )
    3VCP$PQ"451SPDFTTFE4PVSDF
    w ྫ͑͹"45͸ιʔείϝϯτΛදݱͤͣɺ
    ॲཧ͍ͯ͠Διʔείʔυͦͷ΋ͷͷ৘ใΛ
    ද͢ͷ͕1SPDFTTFE4PVSDFΦϒδΣΫτͰ͢
    w 1SPDFTTFE4PVSDF͸ޙड़͢Δ$PQ ϧʔϧ࣮૷

    ͔Β΋ΞΫηεՄೳͳΦϒδΣΫτͰ͢

    View full-size slide

  41. require 'rubocop-ast'
    RuboCop::AST::ProcessedSource.new(
    'puts "hello"', 3.1
    )
    ୈҾ਺ͷҙຯ

    View full-size slide

  42. "451SPDFTTFE4PVSDFQBSTFS@DMBTT
    w 3VCZͷόʔδϣϯ͝ͱͷ
    ߏจղੳ͕༻ҙ͞Ε͍ͯΔ
    1BSTFSHFNͷ"1*બఆ͢Δ
    w Ͳͷ3VCZόʔδϣϯͷߏจ
    ΛղੳΛ͢Δ͔ܾΊΔҾ਺
    ʹͳ͍ͬͯΔ

    View full-size slide

  43. require 'rubocop-ast'
    RuboCop::AST::ProcessedSource.new(
    'puts "hello"', 3.1
    )
    3VCP$PQ"451SPDFTTFE4PVSDF

    View full-size slide

  44. 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

    View full-size slide

  45. 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

    View full-size slide

  46. w 1BSTFSఏڙͷ/PEF
    Λܧঝͨ͠ศར"1*
    w 3VCP$PQ"45ͷ
    શϊʔυ͕ܧঝ͢Δ
    εʔύʔΫϥε
    w 3VCP$PQϧʔϧ࣮૷
    ͷࡍʹ౓ʑࢀর͢Δ
    IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEFSC
    3VCP$PQ"45/PEF

    View full-size slide

  47. 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

    View full-size slide

  48. 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"

    View full-size slide

  49. 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
    ͸ຊฤͰͷݤͰ͢💡

    View full-size slide

  50. w "45ͷύλʔϯϚον
    Λ͢ΔϛχϚϜݴޠ
    w Ϛονͨ͠஋ΛΩϟϓ
    νϟ͢Δ͜ͱ͕Ͱ͖Δ
    w EFG@OPEF@NBUDIFS
    ͳͲͷҾ਺ʹ࢖ΘΕΔ
    IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEF@QBUUFSOSC
    3VCP$PQ"45/PEF1BUUFSO

    View full-size slide


  51. ੩తղੳͷ͘͠Έޙฤ

    View full-size slide

  52. w ղੳର৅ͷ3VCZίʔυͷೖྗͱղੳ݁Ռͷ
    Ϩϙʔτग़ྗ
    w 3VCP$PQͷϧʔϧ࣮૷ͳΒͼʹ֦ு"1*ఏڙ
    w ϢʔβʔͷΧελϜઃఆɺΦϓγϣϯͷղऍ
    w σϑΥϧτϧʔϧ͸SVCZTUZMFHVJEFʹ४ͣΔ
    3VCP$PQ

    View full-size slide

  53. 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

    View full-size slide

  54. 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

    View full-size slide

  55. wSVCPDPQίϚϯυͷϞδϡʔϧͰ͋
    Δ$-*Ϟδϡʔϧ͔Βݺͼग़͞ΕΔ
    wݕࠪର৅ͷϑΝΠϧύεΛݩʹղੳ
    ͱϧʔϧΛద༻͢Δ಺෦Ϟδϡʔϧ
    ܈Λ૬ޓ࡞༻ͤ͞Δ࣮ߦى఺
    3VOOFS

    View full-size slide

  56. wϧʔϧΛ࣮૷ͨ͠$PQ͕ొ࿥͞Ε͍ͯ
    ΔΫϥε
    w📝$PQ#BTFͷ$MBTTJOIFSJUFE࣮૷
    ʹΑͬͯɺ͢΂ͯͷ$PQ͸3FHJTUSZʹ
    ొ࿥͞Ε͍ͯΔ ΋ͬͱ͍ܰͨ͘͠

    3FHJTUSZ

    View full-size slide

  57. wಈһ NPCJMJ[F
    ͞Εͨ$PQΛߏ੒
    ͢ΔΫϥε👮👮👮👮👮
    wΧελϚΠζ͞ΕͨϧʔϧʹԠ͡
    ͨνʔϜ͕૊·ΕΔ
    5FBN

    View full-size slide

  58. IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCNBTUFSMJCSVCPDPQDPQUFBNSC
    5FBN ಈһ

    ༗ޮԽ͞ΕͨϧʔϧͰ͋Δ$PQͷ
    ΫϥεΛ3FHJTUSZ͔Βऔಘͯ͠
    Πϯελϯεੜ੒ͯ͠ฦ͠·͢ɻ
    🚨

    View full-size slide

  59. IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCNBTUFSMJCSVCPDPQDPQUFBNSC
    5FBN ௐࠪ

    ద༻͢Δ$PQͰߏ੒͢Δ
    νʔϜͱߏจղੳͯ͠Δ
    1SPDFTTFE4PVSDFΛݩ
    ʹ$PNNJTTJPOFSΛݺͿ
    🚨
    🔎

    View full-size slide

  60. w੩తղੳΛऔΓ࢓੾Δॺ௕👮
    wಈһ͞Εͨ$PQͨͪ 5FBN
    ʹΑͬͯ
    ༰ٙऀ ίʔυ
    Λݕࠪ͢Δ
    wͦͷਖ਼ମ͸"455SBWFSTBMΛNJYJOͨ͠
    Ϋϥεɻॺ௕ࣗΒ଍Ͱ૞ࠪ͢Δ XBML

    $PNNJTTJPOFS

    View full-size slide

  61. $PNNJTTJPOFS ϝλ


    XBMLͰݺͼग़͞ΕΔίʔϧόοΫ
    ϝιουΛϝλϓϩάϥϛϯάͰ
    ఆ͍ٛͯ͠Δ
    IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCWMJCSVCPDPQDPQDPNNJTTJPOFSSC

    View full-size slide

  62. $PNNJTTJPOFS XBML


    JOWFTUJHBUFʹ౉͞Εͨ
    1SPDFTTFE4PVSDFΛ΋ͱʹ͠
    ͨ"45ΛҾ਺ʹXBMLϝιου
    ΛݺͿ
    XBML͔ΒίʔϧόοΫ͞Εͨ
    PO@YYYϝιουͱಉ໊Ͱ$PQʹ
    ఆٛ͞Ε͍ͯΔPO@YYYʹҠৡ͢Δ
    IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCWMJCSVCPDPQDPQDPNNJTTJPOFSSC
    🔎

    View full-size slide

  63. 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

    View full-size slide

  64. w$PQͷεʔύΫϥε👮
    wϧʔϧΛ࣮૷͢Δ͢΂ͯͷ$PQ͸
    $PQ#BTFΛܧঝ͢Δ
    w📝$PQ$PQ͸ݹ͍ඇਪ঑ͷεʔύʔΫϥ
    εͳͷͰɺ$PQ#BTFʹߋ৽͠·͠ΐ͏
    $PQ#BTF

    View full-size slide

  65. w$PQ#BTFΛܧঝ࣮͠ࡍͷϧʔϧΛ࣮૷ͨ͠
    $PQ👮
    w$PQ͸ඞͣԿΒ͔ͷ෦ॺʹॴଐ͢Δ
    wFH4UZMF4USJOH-JUFSBMTDPQ
    w૊ΈࠐΈ$PQͱࣗ࡞$PQͰ࣮૷ͷҧ͍͸ͳ͍
    ΧελϜ$PQ %FQU$VTUPN$PQ

    View full-size slide

  66. module Cop
    module Style
    class MixinUsage < Base
    MSG = '`%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 ϧʔϧ
    ͷ࣮૷ྫ

    View full-size slide

  67. ϧʔϧ࣮૷ͷৄࡉ͸ެࣜจॻ΁
    IUUQTEPDTSVCPDPQPSHSVCPDPQEFWFMPQNFOUIUNM

    View full-size slide

  68. ࣮૷ࣄྫ͸3VCZ,BJHJಈը΁
    IUUQTSVCZLBJHJPSHQSFTFOUBUJPOTLPJDIUNMKVO

    View full-size slide

  69. "
    ;ͨͭͷόʔδϣϯ

    View full-size slide

  70. w3VCP$PQͰ͸ɺ3VCZҎ্ͷ੩తղੳ͕ɺ
    3VCZҎ্ͷϥϯλΠϜͰՄೳ
    wϥϯλΠϜཁٻͷ3VCZͷόʔδϣϯ͸3VCP$PQࣗମͷ
    ίʔυ͕ॻ͔ΕͯΔ3VCZόʔδϣϯͰ͋Γ3VCZຊମ͕
    ղੳධՁ͢Δ
    w੩తղੳͷίʔυ͸1BSTFSHFNͰղੳ͢Δ
    wSVCPDPQZNMͷ5BSHFU3VCZ7FSTJPOͰWFSTJPOࢦఆՄ
    ղੳόʔδϣϯͱ࣮ߦόʔδϣϯ

    View full-size slide

  71. 4VQQPSUNBUSJY W


    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌
    ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
    ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
    ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
    ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
    ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
    "OBMZTJT3VCZWFSTJPOT TargetRubyVersionJOSVCPDPQZNM

    3VOUJNF3VCZWFSTJPOT
    ruby -v

    View full-size slide

  72. 3VCZͰ3VCZΛղੳ͢Δ
    ࣈ۟ղੳ ߏจղੳ ੩తղੳ
    Ϩϙʔτ
    ιʔείʔυ
    ೖྗ
    ॲཧ
    ग़ྗ
    3VCZॲཧܥͷղੳධՁ
    3BDDʹΑΔߏจղੳ

    View full-size slide

  73. lίʔυΛখઆͷΑ͏ʹಡΜͰɺ
    ಠ૑తͳےॻ͖΍ࢥ͍΋ΑΒ͵ن
    ଇੑΛָ͠Έ·͠ΐ͏ɻҰݟඇৗ
    ʹෳࡶͳ΋ͷΛίϯύΫτͰΤϨ
    Ψϯτͳߏ଄Ͱ࣮ݱ͍ͯ͠Δ΋ͷ
    Λݟ͚ͭΔ͜ͱ΋͋Ε͹ɺখઆͳ
    ͕ΒوॏͳๅੴͷΑ͏ͳίʔυΛ
    ݟ͚ͭΔ͜ͱ΋͋Γ·͢ɻz
    $PEF3FBEJOH

    View full-size slide