# Perl プログラムで Perl プログラムを<br> 修正する方法 Kang-min Liu // @gugod LINE Fukuoka YAPC Tokyo Note: ...についで紹介しています --- 自動修復? ![](https://i.imgur.com/mim74ik.jpg) --- PPI で コードを 変更 --- # [PPI](https://metacpan.org/pod/PPI) Perl5 code を DOM にする ```perl $doc = PPI::Document->new('Module.pm'); $doc->prune('PPI::Token::Comment'); $doc->save('Module.pm'); ``` ---- ## element を取得: find / find_first ```perl # ArrarRef[ PPI::Element ] | undef $elements = $doc->find('PPI::Token::Whitespace'); # ArrarRef[ PPI::Element ] | undef $elements = $doc->find(sub { $_[1]->isa('PPI::Statement::Sub') && $_[1]->name eq 'hoge' }); # PPI::Element | undef $element = $doc->find_first(sub { $_[1]->isa('PPI::Token::Symbol') && $_[1]->content eq '$hoge' }); ``` Note: find method で pattern を指定して、 (指定: してい) element objects として取得できます (取得: しゅとく) ---- ## 削除する (`remove`) ```perl if ($found = $doc->find(...)) { for my $elem (@$found) { $elem->remove; } } ``` Note: 削除 さくじょ method call メソッド コール ---- ## 挿入する (`insert_*`) ```perl $new_elem = ...; # 作る $elem = $doc->find_first(...); $elem->insert_before( $new_elem ); $elem->insert_after( $new_elem ); ``` Note: 付け加える = つけくわえる 挿入 = そうにゅう ---- ## Cut + Paste ```perl my $doc2 = PPI::Document->new(\$code_str); my @new_elems = $doc2->children; my $e = $doc->find_first(...); for (@new_elems) { $_->remove; # cut $e->insert_before($_); # paste } ``` $e のまえに paste Note: PPI::Document::Fragement exists but it is not really integrated with rest of PPI ---- ## Bug を捜査 ```perl $bug = $doc->find( ??? ) ``` --- # [Perl::Critic](https://metacpan.org/pod/Perl::Critic) Critique Perl source code for best-practices. Perl code を評価する ---- ## [ProhibitStringyEval](https://metacpan.org/pod/Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval) ```perl eval "print $foo"; # not ok eval { print $foo }; # ok ``` ---- ## [ProhibitConditionalDeclarations](https://metacpan.org/source/PETDANCE/Perl-Critic-1.132/lib/Perl/Critic/Policy/Variables/ProhibitConditionalDeclarations.pm) ```perl my $foo = $baz if $bar; #not ok my $foo = $baz unless $bar; #not ok our $foo = $baz for @list; #not ok local $foo = $baz foreach @list; #not ok ``` ---- ## [Perl::Critic::TooMuchCode](https://metacpan.org/pod/Perl::Critic::TooMuchCode) Find Dead code (ゴミコード) - 未使用の定数 - 未使用の関数 - 未使用のインポート [✹](https://fastapi.metacpan.org/source/GUGOD/Perl-Critic-TooMuchCode-0.12/lib/Perl/Critic/Policy/TooMuchCode/ProhibitUnusedImport.pm) - 未使用のハッシュキーや値 - 二重定義した関数 [✹](https://fastapi.metacpan.org/source/GUGOD/Perl-Critic-TooMuchCode-0.12/lib/Perl/Critic/Policy/TooMuchCode/ProhibitDuplicateSub.pm) --- code review は bot がしてくれて 良いやん ---- ## [reviewdog](http://haya14busa.com/reviewdog/) Reviewdog を飼ってコードレビューや開発を改善しませんか ![](https://raw.githubusercontent.com/haya14busa/i/d598ed7dc49fefb0018e422e4c43e5ab8f207a6b/reviewdog/reviewdog.logo.png) ---- ## [perlcritic](http://perlcritic.com/) + [reviewdog](http://haya14busa.com/reviewdog/) CI で code review しましょう ``` # .reviewdog.yml runner: perlcritic: cmd: perlcritic --profile .perlcriticrc --verbose 1 *.psgi lib/ errorformat: - "%f:%l:%c:%m" name: perlcritic ``` ---- ## perlcritic + reviewdog ![](https://i.imgur.com/znSEqcV.png) ---- ## perlcritic + reviewdog Docker Image: https://hub.docker.com/r/gugod/perlcritic-reviewdog Drone CI に使用可能 --- bot が 修正してくれません ? --- # p5-nitpick (experimental project) https://github.com/gugod/p5-nitpick nits (小さいゴミ) を自動的に取り除く Note: 取り除く: とりのぞく ---- - RemoveUnusedInclude 未使用 module を取り除く - RemoveUnusedVariables 未使用変数を取り除く [✹](https://github.com/gugod/p5-nitpick/blob/master/lib/App/P5Nitpick/Rule/RemoveUnusedVariables.pm) - DedupeIncludeStatements 重複したincludeを取り除く [✹](https://github.com/gugod/p5-nitpick/blob/master/lib/App/P5Nitpick/Rule/DedupeIncludeStatements.pm) - RemoveUnusedImport 未使用インポートを取り除く [✹](https://github.com/gugod/p5-nitpick/blob/master/lib/App/P5Nitpick/Rule/RemoveUnusedImport.pm) - RewriteWithAssignmentOperators [✹](https://github.com/gugod/p5-nitpick/blob/master/lib/App/P5Nitpick/Rule/RewriteWithAssignmentOperators.pm) ---- - MoreOrLessSpaces whitespace 調整 - QuoteSimpleStringWithSingleQuote "foo" => 'foo' - RemoveEffectlessUTF8Pragma - AppendUnimportStatement - RewriteHeredocAsQuotedString - RewriteRefWithRefUtil - RewriteWithAssignmentOperators ---- ## もっと 修正できる パターン - `do_this();;` semi-colons 多すぎ / empty statements. - ドキュメント の スペルミス - 変数名にスベルミス ---- ```perl # A $n = scalar @arr; # B $n = @arr; ``` ---- ```perl # A @a = @{[ "foo", "bar", foo() ]}; # B @a = ("foo", "bar", foo()); ``` ---- ```perl $bugs = $doc->find( ... ) ``` --- ## 最後 - PPI でコードを変更することは簡単 - ゴミコードを検出するのは面倒臭い - bot が code review してくれるのは楽です - 自動的な修復は簡単なことしかできない --- ご清聴 ありがとう ございました
{"tags":"Talk","slideOptions":{"transition":"none"}}
    2825 views