Perlの静的解析入門とPerlリファクタリングツールApp::PRTのご紹介

Cc696ce673253d3bd21b3aa9e7927f39?s=47 hitode909
August 30, 2014

 Perlの静的解析入門とPerlリファクタリングツールApp::PRTのご紹介

YAPC::Asia Tokyo 2014で発表しました

Cc696ce673253d3bd21b3aa9e7927f39?s=128

hitode909

August 30, 2014
Tweet

Transcript

  1. ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ IUUQQIPUPTBOPHSBQIJYOFU 14೥8݄30೔౔༵೔

  2. IUUQQIPUPTBOPHSBQIJYOFU ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ 14೥8݄30೔౔༵೔

  3. IUUQQIPUPTBOPHSBQIJYOFU ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ 14೥8݄30೔౔༵೔

  4. IUUQQIPUPTBOPHSBQIJYOFU ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ 14೥8݄30೔౔༵೔

  5. IUUQQIPUPTBOPHSBQIJYOFU ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ 14೥8݄30೔౔༵೔

  6. IUUQQIPUPTBOPHSBQIJYOFU ։ԋ·Ͱͷؒ ژ౎ͷࣸਅΛ ָ͓͠Έ͍ͩ͘͞ 14೥8݄30೔౔༵೔

  7. 1FSMͷ੩తղੳ ೖ໳ͱ1FSM ϦϑΝΫλϦϯά πʔϧ "QQ135 ͷ͝঺հ IJUPEF 14೥8݄30೔౔༵೔

  8. IJUPEF झຯ͸ϚϦϯεϙʔπͰ͢ 14೥8݄30೔౔༵೔

  9. 14೥8݄30೔౔༵೔

  10. 14೥8݄30೔౔༵೔

  11. ΋͘͡ 14೥8݄30೔౔༵೔

  12. ΋͘͡ ϦϑΝΫλϦϯάʹ͍ͭͯ 1FSMͷϦϑΝΫλϦϯά ੩తղੳೖ໳ ੩తղੳ࿅श ϦϑΝΫλϦϯάπʔϧͷ঺հ ϦϑΝΫλϦϯά࿅श ࣄྫ঺հ 14೥8݄30೔౔༵೔

  13. 4&&"-40 14೥8݄30೔౔༵೔

  14. Perl::Lint - Yet Another Perl Source Code Linter 14೥8݄30೔౔༵೔

  15. ΋͘͡ ϦϑΝΫλϦϯάʹ͍ͭͯ 1FSMͷϦϑΝΫλϦϯά ੩తղੳೖ໳ ੩తղੳ࿅श ϦϑΝΫλϦϯάπʔϧͷ঺հ ϦϑΝΫλϦϯά࿅श ࣄྫ঺հ 14೥8݄30೔౔༵೔

  16.  14೥8݄30೔౔༵೔

  17. ΋͘͡ ϦϑΝΫλϦϯάʹ͍ͭͯ 1FSMͷϦϑΝΫλϦϯά ੩తղੳೖ໳ ੩తղੳ࿅श ϦϑΝΫλϦϯάπʔϧͷ঺հ ϦϑΝΫλϦϯά࿅श ࣄྫ঺հ 14೥8݄30೔౔༵೔

  18. ϦϑΝΫλϦϯά 14೥8݄30೔౔༵೔

  19. 14೥8݄30೔౔༵೔

  20. ϦϑΝΫλϦϯάͱ͸ɺι ϑτ΢ΣΞͷ֎෦తৼΔక ͍Λอͬͨ··Ͱɺ಺෦ͷ ߏ଄Λվળ͍ͯ͘͠࡞ۀΛ ࢦ͠·͢ɻ 14೥8݄30೔౔༵೔

  21. ৼ෣͍Λม͑ͣʹ ίʔυΛ͖Ε͍ʹ 14೥8݄30೔౔༵೔

  22. ѱ໊͍લΛม͑Δ 14೥8݄30೔౔༵೔

  23. ࣮૷Λྑ͍৔ॴʹҠ͢ 14೥8݄30೔౔༵೔

  24. ࡞ઓߟ͑Δͷ͸೉͍͠ ࡞ۀࣗମ͸؆୯ 14೥8݄30೔౔༵೔

  25. ϦϑΝΫλϦϯάࣗମͷ ࿩͸͠·ͤΜ 14೥8݄30೔౔༵೔

  26. 14೥8݄30೔౔༵೔

  27. δϟό 14೥8݄30೔౔༵೔

  28. IUUQTUBDLPWFSqPXDPNRVFTUJPOTDIBOHFOBNFPGBQBDLBHFBGUFSJGJUJTDSFBUFEBOEIBWFDMBTTFTJOFDMJQTFQPT 14೥8݄30೔౔༵೔

  29. 1FSMͷ৔߹ 14೥8݄30೔౔༵೔

  30. 1FSMͷ৔߹ ͕Μ͹Δ 14೥8݄30೔౔༵೔

  31. ιʔείʔυΛΤσΟλͰ ॻ͖׵͑Δ ݺͼग़͠ݩ΋ॻ͖׵͑Δ ςετ͋Ε͹࣮ߦ ಈ͚͹ϥοΩʔ 14೥8݄30೔౔༵೔

  32. ͳΜ͔ͳͷ͍ͷ͔ 14೥8݄30೔౔༵೔

  33. 1BESF UIF1FSM*%& 1FSM༻ͷ*%& ม਺໊มߋͰ͖Δ ͏·͘ಈ͔ͳ͔ͬͨ ͙͢Ϋϥογϡ͢Δ 14೥8݄30೔౔༵೔

  34. %FWFM3FGBDUPS my $refactory = Devel::Refactor->new; $refactory->rename_subroutine( './path/to/dir', 'oldSubName','newSubName' ); ೥ͷϞδϡʔϧ

    αϒϧʔνϯͷϦωʔϜ 14೥8݄30೔౔༵೔
  35. %FWFM3FGBDUPS my $regex1 = '(\W)(' . $old_name . ')(\W)'; my

    $regex2 = "^$old_name(" . '\W)'; while (<$fh>) { $line_number++; if (/$regex1/o or /$regex2/o) { my $new_line = $_; $new_line =~ s/$regex1/$1$new_name$3/g; $new_line =~ s/$regex2/$new_name$1/; ਖ਼نදݱͰஔ׵ 14೥8݄30೔౔༵೔
  36. %FWFM3FGBDUPS sub _syntax_check{ my $self = shift; my $tmp; my

    $eval_stmt = "my (". join ', ', @{$self->{parms}}; $eval_stmt .= ");\n"; $eval_stmt .= $self->get_sub_call(); $eval_stmt .= $self->get_new_code(); $self->{eval_code} = $eval_stmt; eval " $eval_stmt "; if ($@) { $self->{eval_err} = $@; FWBMͯ͠੒ޭ͔ͨ͠ݟΔ ͱʹ͔͘ϫΠϧυ 14೥8݄30೔౔༵೔
  37. "QQ&EJUPS5PPMT &NBDT7JN༻ϓϥάΠϯ ίϚϯυ ϑΝΠϧ໊͔ΒQBDLBHF໊ਪଌͯ͠ೖྗ ม਺໊มߋ બ୒ൣғΛม਺ʹ͘͘Γग़͠ ͳ͔ͳ͔Α͍͚Ͳ΋͏ͪΐͬͱ 14೥8݄30೔౔༵೔

  38. 5SZJOHUPSFGBDUPS 1FSMDPEF 14೥8݄30೔౔༵೔

  39. ͦ΋ͦ΋ ϦϑΝΫλϦϯά ͢Δʹ͸ 14೥8݄30೔౔༵೔

  40. TFE 14೥8݄30೔౔༵೔

  41. 14೥8݄30೔౔༵೔

  42. จࣈྻૢ࡞Ͱ͸ਫ਼౓ѱ͍ 14೥8݄30೔౔༵೔

  43. 14೥8݄30೔౔༵೔

  44. TFE͸ਫ਼౓௿͍ my $blog = shift; print $blog->{id}; print $blog->{user_id}; my

    $blog = shift; print $blog->{article_id}; print $blog->{user_article_id}; sed -e “s/id/article_id/” 14೥8݄30೔౔༵೔
  45. ͦ͜Ͱ੩తղੳ 14೥8݄30೔౔༵೔

  46. ੩తղੳ ϓϩάϥϜΛ࣮ߦͤͣʹௐ΂Δ ࣮ߦ͢ΔͱಈతղੳʹͳΔ 14೥8݄30೔౔༵೔

  47. ͍ͭ੩తղੳ͢Δͷ γϯλοΫεϋΠϥΠτ ߏจνΣοΫ ίʔσΟϯάن໿ʹԊͬͯΔ͔ ੬ऑੑΛ୳͢ ϦϑΝΫλϦϯά 14೥8݄30೔౔༵೔

  48. ࡶͳ੩తղੳ ϓϩάϥϜΛ࣮ߦͤͣʹ ϓϩάϥϜͷੑ࣭Λௐ΂͍ͯΔ DBUMJC1MBDLQNcXDM  14೥8݄30೔౔༵೔

  49. ؆୯Ͱ͠ΐ ߦ਺͡Όͳ໋ͯ͘ྩ਺஌Γ͍ͨ 14೥8݄30೔౔༵೔

  50. ;ͭ͏ͷ੩తղੳ 14೥8݄30೔౔༵೔

  51. ;ͭ͏ͷ੩తղੳ ߏจ໦Λ࡞ͬͯௐ΂Δ 14೥8݄30೔౔༵೔

  52. print (1 * 2) + 3; ߏจ໦ 14೥8݄30೔౔༵೔

  53. ‘;’ ߏจ໦ ‘print’ ‘ ‘ List ‘ ‘ ‘ ‘

    ‘1’ ‘ ‘ ‘*’ ‘ ‘ ‘2’ ‘+’ ‘3’ Statement Document print (1 * 2) + 3; 14೥8݄30೔౔༵೔
  54. ߏจ໦ print "(1 * 2) + 3"; 14೥8݄30೔౔༵೔

  55. ‘;’ ߏจ໦ ‘print’ ‘ ‘ Statement Document print "(1 *

    2) + 3"; ‘"(1 * 2) + 3"’ 14೥8݄30೔౔༵೔
  56. ͜ΕͳΒ҆৺ 14೥8݄30೔౔༵೔

  57. ߏจ໦Ͳ͏΍ͬͯ࡞Δͷ 14೥8݄30೔౔༵೔

  58. 11* 14೥8݄30೔౔༵೔

  59. 11* 1FSMղੳͯ͘͠ΕΔϞδϡʔϧ 1FSM%PDVNFOU0CKFDU.PEFM 1FSMύʔε͢Δͷ͸೉͍͠ͷͰ͍͢͝ 14೥8݄30೔౔༵೔

  60. ࡶஊ $PNQJMFS-FYFS͍ͬͯ͏ ଎͍ͷ΋͋Δ͚Ͳͦͷ࿩͸͠·ͤΜ ࡢ೔ͷNP[OJPOͷൃදݟͯ 14೥8݄30೔౔༵೔

  61. 11*Ͱ༡΅͏ 14೥8݄30೔౔༵೔

  62. 11*Ͱߏจ໦ݟ͍ͨ print (1 * 2) + 3; 11*%PDVNFOU 11*4UBUFNFOU 11*5PLFO8PSEQSJOU

    11*5PLFO8IJUFTQBDF 11*4USVDUVSF-JTU  11*4UBUFNFOU&YQSFTTJPO 11*5PLFO/VNCFS 11*5PLFO8IJUFTQBDF 11*5PLFO0QFSBUPS  11*5PLFO8IJUFTQBDF 11*5PLFO/VNCFS 11*5PLFO8IJUFTQBDF 11*5PLFO0QFSBUPS  11*5PLFO8IJUFTQBDF 11*5PLFO/VNCFS 11*5PLFO4USVDUVSF 11*5PLFO8IJUFTQBDFaO use PPI; use PPI::Dumper; my $document = PPI::Document->new($ARGV[0]); my $dumper = PPI::Dumper->new($document); $dumper->print; 14೥8݄30೔౔༵೔
  63. ‘;’ Ͱ͖ͨ ‘print’ ‘ ‘ List ‘ ‘ ‘ ‘

    ‘1’ ‘ ‘ ‘*’ ‘ ‘ ‘2’ ‘+’ ‘3’ Statement Document print (1 * 2) + 3; 14೥8݄30೔౔༵೔
  64. 11*Ͱ໋ྩ਺ݟ͍ͨ my $document = PPI::Document->new($ARGV[0]); my $statements = $document->find('PPI::Statement'); my

    $statement_count = @$statements; say "count: $statement_count"; 14೥8݄30೔౔༵೔
  65. 11*Ͱ'J[[#V[[Λഁյ͍ͨ͠ use PPI; my $path = $ARGV[0]; my $document =

    PPI::Document->new($path); my $tokens = $document->find('PPI::Token'); for my $token (@$tokens) { if (ref $token eq 'PPI::Token::Number') { $token->set_content($token->content * 2); } } $document->save("broken-$path"); 14೥8݄30೔౔༵೔
  66. 11*Ͱ'J[[#V[[Λഁյ͍ͨ͠ use PPI; my $path = $ARGV[0]; my $document =

    PPI::Document->new($path); my $tokens = $document->find('PPI::Token'); for my $token (@$tokens) { if (ref $token eq 'PPI::Token::Number') { $token->set_content($token->content * 2); } } $document->save("broken-$path"); ਺ࣈΛݟ͚ͭͨΒ ͱΓ͋͑ͣഒʹ͢Δ 14೥8݄30೔౔༵೔
  67. ͜Ε͕ use strict; use warnings; for my $i (1..20) {

    my $message = ""; $message .= "Fizz" unless $i % 3; $message .= "Buzz" unless $i % 5; $message = $i unless $message; print "$message\n"; } 14೥8݄30೔౔༵೔
  68. ͜͏ use strict; use warnings; for my $i (2..40) {

    my $message = ""; $message .= "Fizz" unless $i % 6; $message .= "Buzz" unless $i % 10; $message = $i unless $message; print "$message\n"; } 14೥8݄30೔౔༵೔
  69. -(5.  'J[[    #V[[  'J[[ 

        'J[[  #V[[    'J[[      'J[[#V[[      'J[[  14೥8݄30೔౔༵೔
  70. 'J[[#V[[ʹݶΒͣ ഁյͰ͖Δ 14೥8݄30೔౔༵೔

  71. ΢ΣϒΞϓϦέʔγϣϯΛഁյ 14೥8݄30೔౔༵೔

  72. my $app = sub { return [ 200, [ 'Content-Type'

    => 'text/plain' ], [ 'Hello World' ] ]; }; 14೥8݄30೔౔༵೔
  73. my $app = sub { return [ 400, [ 'Content-Type'

    => 'text/plain' ], [ 'Hello World' ] ]; }; 14೥8݄30೔౔༵೔
  74. my $app = sub { return [ 400, [ 'Content-Type'

    => 'text/plain' ], [ 'Hello World' ] ]; }; ഒ 14೥8݄30೔౔༵೔
  75. ϙΠϯτ 14೥8݄30೔౔༵೔

  76. ϙΠϯτ ߏจ໦Λॻ͖׵͑ͯอଘ 14೥8݄30೔౔༵೔

  77. ศརͳྫ 14೥8݄30೔౔༵೔

  78. HJUHSFQͷ͍͍΍ͭ 14೥8݄30೔౔༵೔

  79. HJUHSFQͷ͍͍΍ͭ "QQ(JU(SFQ1FSM4UBUFNFOU git grep-perl-statement finalize t/ τʔΫϯ୯ҐͰݕࡧ εςʔτϝϯτ୯ҐͰදࣔ 14೥8݄30೔౔༵೔

  80. HJUHSFQͷ͍͍΍ͭ HJUHSFQͰϑΝΠϧ୳͢ Ϛονͨ͠ϑΝΠϧͷߏจ໦࡞Δ TUBUFNFOUΛݸͣͭݟΔ TUBUFNFOU͕୳ͯ͠ΔUPLFOΛؚΊ͹දࣔ 14೥8݄30೔౔༵೔

  81. งғؾ my $doc = PPI::Document->new($file); my $statements = $doc->find('PPI::Statement'); grep

    { my $tokens = [ $_->children ]; any { $_ eq $self->word; } @$tokens; } @$statements; 14೥8݄30೔౔༵೔
  82. ίʔσΟϯάελΠϧ ௐ΂Δ΍ͭ 14೥8݄30೔౔༵೔

  83. 1FSM$SJUJD ίʔσΟϯάελΠϧௐ΂ͯ͘ΕΔ νʔϜ಺ͰελΠϧ౷Ұ͢Δͷʹศར 14೥8݄30೔౔༵೔

  84. Ұൠతͳ1FSMϞδϡʔϧ ͷελΠϧΛνΣοΫͯ͠ Έ·͠ΐ͏ 14೥8݄30೔౔༵೔

  85. package Antipop; use strict; use warnings; our $VERSION = '0.01';

    sub talk { return q{ҿΈʹߦͧ͘!!1}; } !!1; __END__ 14೥8݄30೔౔༵೔
  86. QFSMDSJUJD"OUJQPQQN 14೥8݄30೔౔༵೔

  87. QFSMDSJUJD"OUJQPQQN .PEVMFEPFTOPUFOEXJUIBUMJOF DPMVNO .VTUFOEXJUIBSFDPHOJ[BCMFUSVFWBMVF 4FWFSJUZ 14೥8݄30೔౔༵೔

  88. QFSMDSJUJD"OUJQPQQN .PEVMFEPFTOPUFOEXJUIBUMJOF DPMVNO .VTUFOEXJUIBSFDPHOJ[BCMFUSVFWBMVF 4FWFSJUZ !!1; 14೥8݄30೔౔༵೔

  89. 1FSM$SJUJD1PMJDZ.PEVMFT3FRVJSF&OE8JUI0OF sub violates { my ( $self, $elem, $doc )

    = @_; # Last statement should be just "1;" my @significant = grep { _is_code($_) } $doc->schildren(); my $match = $significant[-1]; return if !$match; return if ((ref $match) eq 'PPI::Statement' && $match =~ m{\A 1 \s* ; \z}xms ); # Must be a violation... return $self->violation( $DESC, $EXPL, $match ); } 14೥8݄30೔౔༵೔
  90. ੩తղੳͰ ͠ΐ΅͍෺͔Β ෳࡶͳ෺·Ͱ 14೥8݄30೔౔༵೔

  91. ੩తղੳͷ࿩͓ΘΓ 14೥8݄30೔౔༵೔

  92. ϦϑΝΫλϦϯάπʔϧͷ࿩ 14೥8݄30೔౔༵೔

  93. "QQ135 14೥8݄30೔౔༵೔

  94. "QQ135 1FSM 3FGBDUPSJOH 5PPM 14೥8݄30೔౔༵೔

  95. "QQ135 1FSM 3FGBDUPSJOH 5PPM ࡞ͬͯ·͢ 14೥8݄30೔౔༵೔

  96. ϦϑΝΫλϦϯά͍ͨ͠ͱ ͖ʹ͋ΔΑ͋͘Δૢ࡞Λ· ͱΊͨπʔϧ 14೥8݄30೔౔༵೔

  97. ίϚϯυϥΠϯ͔Β࣮ߦ ιʔείʔυॻ͖׵͑ͯอଘ 14೥8݄30೔౔༵೔

  98. Ͱ͖Δ͜ͱ 14೥8݄30೔౔༵೔

  99. Ͱ͖Δ͜ͱ τʔΫϯͷஔ׵ ΫϥεͷϦωʔϜ ωʔϜεϖʔεͷϦωʔϜ ϝιουͷ࡟আ ΫϥεϝιουͷҠಈ 14೥8݄30೔౔༵೔

  100. ࿅श 14೥8݄30೔౔༵೔

  101. ࿅श༻ʹ༻ҙͨ͠ ΫιίʔυΛ ϦϑΝΫλϦϯά ͯ͠Έ·͠ΐ͏ 14೥8݄30೔౔༵೔

  102. ͓Έ͘͡ΞϓϦέʔγϣϯ ͷϦϑΝΫλϦϯά IUUQTHJUIVCDPNIJUPEFPNJLVKJ 14೥8݄30೔౔༵೔

  103. QFSMPNJLVKJQM த٢ QFSMPNJLVKJQM த٢ QFSMPNJLVKJQM େ٢ QFSMEPVCVUV@PNJLVKJQM ޕ QFSMEPVCVUV@PNJLVKJQM ਃ

    14೥8݄30೔౔༵೔
  104. 0NJLVKJ VSBOBV VSBOBXBOBJ 0NJLVKJ%PVCVUV VSBOBV 0NJLVKJ6UJM DIPJTF MVDLZ ˚ ܧঝ

    ར༻ 14೥8݄30೔౔༵೔
  105. VSBOBVϝιουΛ ϦωʔϜͯ͠ΈΔ prt replace_token uranau tell 14೥8݄30೔౔༵೔

  106. prt replace_token uranau tell ίϚϯυ αϒίϚϯυ Ҿ਺ 14೥8݄30೔౔༵೔

  107. 0NJLVKJ UFMM VSBOBXBOBJ 0NJLVKJ%PVCVUV UFMM 0NJLVKJ6UJM DIPJTF MVDLZ ˚ ܧঝ

    ར༻ 14೥8݄30೔౔༵೔
  108. 0NJLVKJ6UJMMVDLZϝιουΛ -VDLZΫϥεʹҠಈͯ͠ΈΔ prt move_class_method ‘Omikuji::Util#lucky’ ‘Omikuji::Lucky#get_lucky’ 14೥8݄30೔౔༵೔

  109. 0NJLVKJ UFMM VSBOBXBOBJ 0NJLVKJ%PVCVUV UFMM 0NJLVKJ6UJM DIPJTF ˚ ܧঝ ར༻

    0NJLVKJ-VDLZ HFU@MVDLZ 14೥8݄30೔౔༵೔
  110. 0NJLVKJ6UJMΫϥεΛ 0NJLVKJ-JTUΫϥεʹ ϦωʔϜ prt rename_class Omikuji::Util Omikuji::List 14೥8݄30೔౔༵೔

  111. 0NJLVKJ UFMM VSBOBXBOBJ 0NJLVKJ%PVCVUV UFMM 0NJLVKJ-JTU DIPJTF ˚ ܧঝ ར༻

    0NJLVKJ-VDLZ HFU@MVDLZ 14೥8݄30೔౔༵೔
  112. 0NJLVKJΫϥεΛ -PUΫϥεʹϦωʔϜ prt rename_class Omikuji Lot 14೥8݄30೔౔༵೔

  113. -PU UFMM VSBOBXBOBJ 0NJLVKJ%PVCVUV UFMM 0NJLVKJ-JTU DIPJTF ˚ ܧঝ ར༻

    0NJLVKJ-VDLZ HFU@MVDLZ 14೥8݄30೔౔༵೔
  114. 0NJLVKJҎԼΛશͯ -PUʹϦωʔϜ prt rename_name_space Omikuji Lot 14೥8݄30೔౔༵೔

  115. -PU UFMM VSBOBXBOBJ -PU%PVCVUV UFMM -PU-JTU DIPJTF ˚ ܧঝ ར༻

    -PU-VDLZ HFU@MVDLZ 14೥8݄30೔౔༵೔
  116. ϦϑΝΫλϦϯά੒ޭ 14೥8݄30೔౔༵೔

  117. ΋͏ͪΐͬͱ େ͖͍ΞϓϦέʔγϣϯͰ ࿅श 14೥8݄30೔౔༵೔

  118. 1MBDL3FRVFTUΛ 1MBDL,VEBTBJʹ 14೥8݄30೔౔༵೔

  119. prt rename_class Plack::Request Plack::Kudasai 14೥8݄30೔౔༵೔

  120. ϦϑΝΫλϦϯά੒ޭ 14೥8݄30೔౔༵೔

  121. ໊લΛؾܰʹ ͋ͱ͔Βม͑ΒΕΔͷ͸ ศར 14೥8݄30೔౔༵೔

  122. ϦϥοΫεͰ͖Δ 14೥8݄30೔౔༵೔

  123. ͏·͘࢖͏ίπ 14೥8݄30೔౔༵೔

  124. ର৅ϑΝΠϧΛߜΔ prt rename_token foo bar $(git grep --name-only foo) ର৅ϑΝΠϧ͕ݮΔͱ଎͍ͧ

    14೥8݄30೔౔༵೔
  125. ςετ௨͔ͯ͠Βίϛοτ ςετ௨͔ͬͯΒ ίϛοτ͢Δͱ҆৺Ͱ͖Δͧ 14೥8݄30೔౔༵೔

  126. ϦϑΝΫλϦϯά͠΍͘͢อͭ ϝλϓϩάϥϛϯάΛආ͚Δ จࣈྻ࿈݁ͰQBDLBHF໊࡞Δͱ೉͍͠ KPJObz b0NJLVKJ` b6UJM` 14೥8݄30೔౔༵೔

  127. ࣄྫ঺հ 14೥8݄30೔౔༵೔

  128. ࣄྫ঺հ ͸ͯͳϒϩάશࣗಈϦϑΝΫλϦϯά 14೥8݄30೔౔༵೔

  129. എܠ 4FSWJDFΫϥεʹ DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠ Service::User->find_user_by_name($r, $name); 14೥8݄30೔౔༵೔

  130. എܠ 4FSWJDFΫϥεʹ DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠ EC͚ͩ౉͢ͱ͜Ζ΋ Service::User->find_user_by_name($r, $name); Service::Blog->find_blog_by_uri($r->db, $uri); 14೥8݄30೔౔༵೔

  131. എܠ 4FSWJDFΫϥεʹ DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠ EC͚ͩ౉͢ͱ͜Ζ΋ ౷Ұ͞Εͯͳͯ͘ΧΦε ΫϥεɼݸҎ্ͷϝιου Service::User->find_user_by_name($c, $name); Service::Blog->find_blog_by_uri($c->db, $uri);

    14೥8݄30೔౔༵೔
  132. എܠ 4FSWJDFΫϥεʹ DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠ EC͚ͩ౉͢ͱ͜Ζ΋ ౷Ұ͞Εͯͳͯ͘ΧΦε ΫϥεɼݸҎ্ͷϝιου खͰͪ·ͪ·௚ͦ͏ͱ͢Δ΋࠳ં Service::User->find_user_by_name($c, $name); Service::Blog->find_blog_by_uri($c->db,

    $uri); 14೥8݄30೔౔༵೔
  133. શࣗಈνϟϯε 14೥8݄30೔౔༵೔

  134. ΍Γ͍ͨ͜ͱ 14೥8݄30೔౔༵೔

  135. Service::User->find_user_by_name($r, $name); sub find_user_by_name { my ($class, $r, $name) =

    @_; $r->db->select(..., $name); } CFGPSF 14೥8݄30೔౔༵೔
  136. Service::User->find_user_by_name($r->db, $name); sub find_user_by_name { my ($class, $db, $name) =

    @_; $db->select(..., $name); } BGUFS 14೥8݄30೔౔༵೔
  137. ࡞ઓ 14೥8݄30೔౔༵೔

  138. Service::User->find_user_by_name($r->db, $name); sub find_user_by_name { my ($class, $db, $name) =

    @_; $db->select(..., $name); } ݺͼग़͠ݩͰ $r → $r->db ݺͼग़͠ઌͰ $r → $db $r->db → $db 14೥8݄30೔౔༵೔
  139. ॻ͖׵͑ͯ͸͍͚ͳ͍৔߹ 14೥8݄30೔౔༵೔

  140. sub aaa { my ($class, $r = @_; AnotherService->bbb($r); $r->db->select(...,

    $user->name); } ΄͔ͷϝιουʹS౉ͯ͠Δ 14೥8݄30೔౔༵೔
  141. sub aaa { my ($class, $r) = @_; AnotherService->bbb($r->db); $r->db->select(...,

    $user->name); } ΄͔ͷϝιουʹS౉ͯ͠Δ ઌʹ"OPUIFS4FSWJDFΛ ϦϑΝΫλϦϯά 14೥8݄30೔౔༵೔
  142. sub aaa { my ($class, $db) = @_; AnotherService->bbb($db); $db->select(...,

    $user->name); } ΄͔ͷϝιουʹS౉ͯ͠Δ ઌʹ"OPUIFS4FSWJDFΛ ϦϑΝΫλϦϯά ϝιου಺͕શͯSECͳΒॻ͖׵͑ΒΕΔ 14೥8݄30೔౔༵೔
  143. sub aaa { my ($class, $r) = @_; my $user

    = $r->user; $r->db->select(..., $user->name); } ECҎ֎΋࢖ͬͯΔ 14೥8݄30೔౔༵೔
  144. sub aaa { my ($class, $r, $user) = @_; $r->db->select(...,

    $user->name); } ECҎ֎΋࢖ͬͯΔ VTFS΋ड͚औΔ ͜Ε͸ػցతʹ͸Ͱ͖ͳ͍ͷͰख࡞ۀ 14೥8݄30೔౔༵೔
  145. ࡞ઓ wιʔείʔυશϑΝΠϧॱ൪ʹݟΔ wSΛड͚औͬͯΔϝιουΛ୳͢ w҆શʹॻ͖׵͑ΒΕΔ wϝιουఆٛΛॻ͖׵͑ˠݺͼग़͠ݩ΋ॻ͖׵͑ wมߋՕॴͷςετ࣮ߦ w௨ͬͨΒDPNNJUQVTIͯ͠࠷ॳʹ໭Δ wམͪͨΒεΫϦϓτऴྃͯ͠ਓؒΛݺͿ w҆શ͡Όͳ͔ͬͨΒ࣍ͷϝιουʹߦ͘ wԿ΋ॻ͖׵͑ͣશϑΝΠϧݟऴΘͬͨΒਓؒΛݺͿ

    14೥8݄30೔౔༵೔
  146. ݟͲ͜Ζ 14೥8݄30೔౔༵೔

  147. ࢦఆ͞ΕͨϑΝΠϧ ॱ൪ʹݟΔ sub replace_all { for my $file (@ARGV) {

    my $document = PPI::Document->new($file); my $package = $document->find_first( 'PPI::Statement::Package' ); my $package_name = $package->namespace; my $methods = $document->find( 'PPI::Statement::Sub' ); for my $method (@$methods) { my $document = PPI::Document->new($file); ...; } } } 14೥8݄30೔౔༵೔
  148. SECΛECʹஔ׵ sub r_db_to_db { my ($statement) = @_; my $tokens

    = [$statement->children]; for my $token (@$tokens) { if ($token eq '$r') { if ($token->next_token eq '->') { if ($token->next_token->next_token eq 'db') { $token->set_content('$db'); $token->next_token->set_content(''); $token->next_token->next_token->set_content(''); } else { die "->@{[ $token->next_token->next_token ]}"; } } else { die "@{[ $token->next_token ]}"; } } } } 14೥8݄30೔౔༵೔
  149. ݺͼग़͠ݩͷมߋ $command = 'prt replace_token \'' . $package_name . '->'

    . $method_name . '($r\' \'' . $package_name . '->' . $method_name . '($r->db\' --in- statement ' . $method_name . ' $(git grep --name-only ' . $method_name . ')'; system $command; 14೥8݄30೔౔༵೔
  150. Ϋϥε಺Ͱͷݺͼग़͠มߋ $command = 'prt replace_token \'$class' . '->' . $method_name

    . '($r\' \'$class' . '->' . $method_name . '($r->db\' --in- statement ' . $method_name . ' ' . $file; system $command; 14೥8݄30೔౔༵೔
  151. มߋՕॴΛςετͯ͠ίϛοτ if (`git diff --name-only t/**.t`) { system('carton exec --

    prove $(git diff -- name-only t/**.t)') and die "test failed"; } else { warn 'skip test'; } system "git commit -am '$package_name\ͷ $method_name\Λ\$db Λड͚औΔΑ͏ʹมߋ'"; system "git push"; 14೥8݄30೔౔༵೔
  152. ॻ͖׵͑ଓ͚Δ my $success = 1; while($success) { $success = replace_all();

    } 14೥8݄30೔౔༵೔
  153. ൒೔ޙ 14೥8݄30೔౔༵೔

  154. 250+ Commits 281 Files changed +2,004 −1,927 14೥8݄30೔౔༵೔

  155. ϦϑΝΫλϦϯά੒ޭ 14೥8݄30೔౔༵೔

  156. ஌ݟ 14೥8݄30೔౔༵೔

  157. ஌ݟ ҙ֎ͱͳΜͱ͔ͳΔ 14೥8݄30೔౔༵೔

  158. ஌ݟ ҙ֎ͱͳΜͱ͔ͳΔ ϨϏϡϫʔ͔Θ͍ͦ͏ 14೥8݄30೔౔༵೔

  159. ஌ݟ ҙ֎ͱͳΜͱ͔ͳΔ ϨϏϡϫʔ͔Θ͍ͦ͏ ௕೥ͷٕज़తෛ࠴Λٕज़Ͱղܾͨ͠ 14೥8݄30೔౔༵೔

  160. Ҏ্ 14೥8݄30೔౔༵೔

  161. ·ͱΊ ϦϑΝΫλϦϯάʹ͍ͭͯ 1FSMͷϦϑΝΫλϦϯά ੩తղੳೖ໳ ੩తղੳ࿅श ϦϑΝΫλϦϯάπʔϧͷ঺հ ϦϑΝΫλϦϯά࿅श ࣄྫ঺հ 14೥8݄30೔౔༵೔

  162. ׬ 14೥8݄30೔౔༵೔

  163. ҰॹʹϦϑΝΫλϦϯά͠·͠ΐ͏ ʲॕʳTPOHNV͞Μೖࣾ 14೥8݄30೔౔༵೔