$30 off During Our Annual Pro Sale. View Details »

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
  2. @koic w044ϓϩάϥϚʔ w3VCP$PQίΞνʔϜ wגࣜձࣾӬ࿨γεςϜϚωδϝϯτ &4. *OD  ΤϯδχΞϦϯάϚωʔδϟʔ݉ σΟεςΟϯάΠογϡυΤϯδχΞ

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

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

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

  7. 5IFpSTUDPNNJU % git log -p --reverse commit afbead34db54506c12a21dbd4ce04fada0f8b9a4 Author: Bozhidar

    Batsov <bozhidar@batsov.com> 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 +++++++++++++
  8. 5IFpSTUDPNNJU % git log -p --reverse commit afbead34db54506c12a21dbd4ce04fada0f8b9a4 Author: Bozhidar

    Batsov <bozhidar@batsov.com> 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 +++++++++++++ 👈
  9. UI"OOJWFSTBSZZFBS🎉

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

  11. None
  12. .BJOUBJO3VCP$PQ)2&WFSZ%BZ IUUQTHJUIVCDPNLPJD PSHSVCPDPQ

  13. .F

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

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

  16.  ߏจղੳͷ͘͠Έ

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

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

    ґଘ͢Δ 1BSTFSHFN
  19. w 3VCZຊମ͕ߏจఆ͍ٛͯ͠ΔQBSTFZͷมߋ Λ௥͍ͬͯΔ ͍ΘΏΔSEύʔςΟ੡඼  w 3VCZຊମͰ৽͍͠ߏจ௥Ճ͕͋ͬͯ΋ 1BSTFSHFNଆͷߏจఆٛʹಉ༷ͷύονΛ खΛೖΕͳ͍ͱɺ৽͍͠ߏจΛղੳͰ͖ͳ͍ w

    ݱࡏ0QBMίϛολʔ͕Ϧʔυ͍ͯ͠Δ 3VCZߏจղੳͷ࣮૷ͷͻͱͭ
  20. ߏจղੳͱͦͷઌ ੩తղੳ 3VCP$PQ 1PMZpMM 3VCZ/FYU τϥϯεύΠϥ 0QBM ߏจղੳ 1BSTFS 3VCZίʔυ

    "45 ݹ͍ϥϯλΠϜ 3VCZίʔυ +BWB4DSJQUίʔυ ੩తղੳޙͷमਖ਼ 3VCZίʔυ 1SPDFTTFE4PVSDF
  21. w 1BSTFSHFN͸όʔδϣϯ͝ͱͷ3VCZߏจΛ #/' όοΧεɾφ΢Ξه๏ Ͱఆٛͯ͠Δ 3VCP$PQ1BSTFS͕ॲཧ͢Δߏจ ͷͪͷ෬ઢʹͳΓ·͢💡

  22. w ίϩϯ  ͷࠨลͷ୯ Ұͷه߸͕ӈลʹߏ੒ ͞Ε͍ͯΔه߸ͷฒͼ Ͱஔ׵͞ΕΔ w 1BSTFSHFNͰ͸3BDD ͱ͍͏ύʔαδΣω

    ϨʔλΛ࢖͍ͬͯΔ Zͷ#/'αϯϓϧ
  23. % 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͕ੜ੒͞ΕΔ
  24. 3VCZ͔Β1BSTFS΁ͷҠ২ྫ

  25. XIJUFRVBSLQBSTFS SVCZZ"MMPXUSBJMJOHDPNNBJOIBTIQBUUFSO

  26. 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
  27. IUUQTHJUIVCDPNSVCZSVCZDPNNJUEBG

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

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

  30. 3VCZ͔Β1BSTFSʹҠ২

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

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

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

  35. w 1BSTFSHFN͸ύʔαδΣωϨʔλ ʹ3BDDΛ࢖͍ͬͯΔ w #/' όοΧεɾφ΢Ξه๏ Ͱ ॻ͔Ε͍ͯΔ w 3BDDΛ࢖ͬͨߏจղੳ͍ͭͯ͸

    ʰຊແಓฤʱͳͲࢀরͷ͜ͱ ߏจղੳೖ໳
  36.  ੩తղੳͷ͘͠Έલฤ

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

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

    1FSGPSNBODF 3VCP$PQ 3BJMT 3VCP$PQͷґଘελοΫ
  39. w Ϣʔβʔ͕௚઀ૢ࡞͢Δ΋ͷͱ͍͏ΑΓ͸ɺ 3FFL΍$-*πʔϧͳΜ͔Ͱ3VCP$PQͷϊʔ υύλʔϯͳͲͷػೳͷΈ࢖͍͍ͨཁ๬͕ ͋ͬͯ੾Γग़͞Εͨ w 5SBWFSTBM 1SPDFTTFE4PVSDF ϊʔυͷύ λʔϯهड़

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

  41. puts "hello" IFMMP αϯϓϧ

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

  43. require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) 3VCP$PQ"451SPDFTTFE4PVSDF w ྫ͑͹"45͸ιʔείϝϯτΛදݱͤͣɺ

    ॲཧ͍ͯ͠Διʔείʔυͦͷ΋ͷͷ৘ใΛ ද͢ͷ͕1SPDFTTFE4PVSDFΦϒδΣΫτͰ͢ w 1SPDFTTFE4PVSDF͸ޙड़͢Δ$PQ ϧʔϧ࣮૷  ͔Β΋ΞΫηεՄೳͳΦϒδΣΫτͰ͢
  44. require 'rubocop-ast' RuboCop::AST::ProcessedSource.new( 'puts "hello"', 3.1 ) ୈҾ਺ͷҙຯ

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

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

  47. 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
  48. 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
  49. w 1BSTFSఏڙͷ/PEF Λܧঝͨ͠ศར"1* w 3VCP$PQ"45ͷ શϊʔυ͕ܧঝ͢Δ εʔύʔΫϥε w 3VCP$PQϧʔϧ࣮૷ ͷࡍʹ౓ʑࢀর͢Δ

    IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEFSC 3VCP$PQ"45/PEF
  50. 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
  51. 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"
  52. 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 ͸ຊฤͰͷݤͰ͢💡
  53. w "45ͷύλʔϯϚον Λ͢ΔϛχϚϜݴޠ w Ϛονͨ͠஋ΛΩϟϓ νϟ͢Δ͜ͱ͕Ͱ͖Δ w EFG@OPEF@NBUDIFS ͳͲͷҾ਺ʹ࢖ΘΕΔ IUUQTHJUIVCDPNSVCPDPQIRSVCPDPQBTUCMPCNBTUFSMJCSVCPDPQBTUOPEF@QBUUFSOSC

    3VCP$PQ"45/PEF1BUUFSO
  54.  ੩తղੳͷ͘͠Έޙฤ

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

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

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

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

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

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

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

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

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

    IUUQTHJUIVCDPNSVCPDPQSVCPDPQCMPCWMJCSVCPDPQDPQDPNNJTTJPOFSSC 🔎
  66. 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
  67. w$PQͷεʔύΫϥε👮 wϧʔϧΛ࣮૷͢Δ͢΂ͯͷ$PQ͸ $PQ#BTFΛܧঝ͢Δ w📝$PQ$PQ͸ݹ͍ඇਪ঑ͷεʔύʔΫϥ εͳͷͰɺ$PQ#BTFʹߋ৽͠·͠ΐ͏ $PQ#BTF

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

  69. 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 ϧʔϧ ͷ࣮૷ྫ
  70. ϧʔϧ࣮૷ͷৄࡉ͸ެࣜจॻ΁ IUUQTEPDTSVCPDPQPSHSVCPDPQEFWFMPQNFOUIUNM

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

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

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

  74. 4VQQPSUNBUSJY W        

          ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌  ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅  ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅  ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅  ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅  ❌ ❌ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ "OBMZTJT3VCZWFSTJPOT TargetRubyVersionJOSVCPDPQZNM 3VOUJNF3VCZWFSTJPOT ruby -v
  75. 3VCZͰ3VCZΛղੳ͢Δ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ 3VCZॲཧܥͷղੳධՁ

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