# 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 してくれるのは楽です
- 自動的な修復は簡単なことしかできない
---
ご清聴
ありがとう
ございました
{"metaMigratedAt":"2023-06-14T19:33:26.091Z","metaMigratedFrom":"YAML","title":"Perl プログラムで Perl プログラムを<br> 修正する方法","breaks":true,"slideOptions":"{\"transition\":\"none\"}","contributors":"[{\"id\":\"dcce249b-7b0f-4093-b97b-479c7762dfba\",\"add\":18564,\"del\":13632}]"}