Python には、不要なステートメントがあるかどうかを知らせるimportcheckerというスクリプトがあります。import
Perl use
(およびrequire
) ステートメント用の同様のユーティリティはありますか?
Python には、不要なステートメントがあるかどうかを知らせるimportcheckerというスクリプトがあります。import
Perl use
(およびrequire
) ステートメント用の同様のユーティリティはありますか?
Devel::TraceUseを見てください。探しているものの一部が得られるかもしれません。
これを試みるために私が書いたスクリプトを次に示します。これは非常に単純化されており、何も自動化することはありませんが、最初に何かを提供します。
#!/usr/bin/perl
use strict;
use v5.14;
use PPI::Document;
use PPI::Dumper;
use PPI::Find;
use Data::Dumper;
my %import;
my $doc = PPI::Document->new($ARGV[0]);
my $use = $doc->find( sub { $_[1]->isa('PPI::Statement::Include') } );
foreach my $u (@$use) {
my $node = $u->find_first('PPI::Token::QuoteLike::Words');
next unless $node;
$import{$u->module} //= [];
push $import{$u->module}, $node->literal;
}
my $words = $doc->find( sub { $_[1]->isa('PPI::Token::Word') } );
my @words = map { $_->content } @$words;
my %words;
@words{ @words } = 1;
foreach my $u (keys %import) {
say $u;
foreach my $w (@{$import{$u}}) {
if (exists $words{$w}) {
say "\t- Found $w";
}
else {
say "\t- Can't find $w";
}
}
}
パッケージをロードしてシンボルをインポートする (またはしない) 方法はいくつかあります。これらのシンボルが使用されているかどうかを単独で直接チェックするツールを知りません。
ただし、明示的なインポート リストが指定されている場合は、
use Module qw(func1 func2 ...);
その多くに役立つPerl::CriticポリシーのTooMuchCode::ProhibitUnusedImportがあります。
1つはコマンドラインで実行されます
perlcritic --single-policy TooMuchCode::ProhibitUnusedImport program.pl
そしてプログラムがチェックされます。または、--single-policy
フラグなしで実行して完全なチェックを行い、出力で違反を探しSeverity 1
ます。これは次のとおりです。
例として、プログラムを考えてみましょう
use warnings;
use strict;
use feature 'say';
use Path::Tiny; # a class; but it imports 'path'
use Data::Dumper; # imports 'Dumper'
use Data::Dump qw(dd pp); # imports 'dd' and 'pp'
use Cwd qw(cwd); # imports only 'cwd'
use Carp qw(carp verbose); # imports 'carp'; 'verbose' isn't a symbol
use Term::ANSIColor qw(:constants); # imports a lot of symbols
sub a_func {
say "\tSome data: ", pp [ 2..5 ];
carp "\tA warning";
}
say "Current working directory: ", cwd;
a_func();
上記のperlcritic
コマンドを実行すると印刷されます
未使用のインポート: dd at line 7, column 5. トークンはインポートされますが、同じコードでは使用されません。(重大度: 1) Unused import: verbose at line 9, column 5. トークンはインポートされますが、同じコードでは使用されません。(重大度: 1)
同じパッケージからは(サブで)使用されているためフラグが付けられていませんが、どちらもdd
使用されていません。当然のことながら、ポリシーの目的から外れています。pp
carp
cwd
ただし、注意してください
:constants
タグが付いているものは何でも見つかりません
verbose
関数ではない (暗黙的に使用される) wordは、未使用として報告されます
が呼び出されa_func()
ない場合、未使用であってもそれらpp
とそのcarp
中は報告されません。コードに存在するため、これは問題ないかもしれませんが、注意する価値があります
(このグリッチ リストはすべてを網羅しているわけではありません。)
インポート リストがインポートサブルーチンに渡されることを思い出してください。インポートサブルーチンは、モジュールの設計が価値があると判断したものを期待して利用する可能性があります。これらは関数名だけである必要はありません。これらすべてをフォローアップすることは、明らかにこのポリシーを超えています。それでも、関数名を含む明示的なインポート リストを使用してモジュールをロードすることは良い方法であり、このポリシーがカバーするものは重要なユース ケースです。
また、明確に述べられているポリシーの使用法によると、Dumper
(インポートされたData::Dumper
) は見つからず、path
からも見つかりませんPath::Tiny
。このポリシーは、いくつかの奇妙なMoose
トリックを扱います。
どうすればより多くのことを行うことができますか? 便利なツールの 1 つは、シンボル テーブルを収集するDevel::Symdumpです。インポートされた上記のプログラムのすべてのシンボルをキャッチします(もちろん、使用されているPath::Tiny
メソッドは表示されません)。ただし、存在しない「シンボル」verbose
も含まれます。追加
use Devel::Symdump;
my $syms = Devel::Symdump->new;
say for $syms->functions;
上記の例に。(ランタイム) require
-ed ライブラリも処理するには、プログラムのどこにでもある可能性がある、それらがロードされた後のコード内の場所でこれを行う必要があります。次に、次のEND
ようにブロックで行うのが最善です
END {
my $ds = Devel::Symdump->new;
say for $ds->functions;
};
次に、これらのうちどれが使用されていないかを確認する必要があります。現時点で、その仕事のために私が知っている最良のツールはPPIです。完全な例を参照してください。別のオプションは、Devel::NYTProfのようなプロファイラーを使用することです。
多少の調整が必要な別のオプション†</sup> は、コンパイラのバックエンドB::Xrefです。これは、プログラムで使用される実質的にすべてのものを取得します。として使用されます
perl -MO=Xref,-oreport_Xref.txt find_unused.pl
(大量の)出力はファイルにありますreport_Xref.txt
。
出力には、関連する各ファイルのセクションがあり、サブルーチンとそのパッケージのサブセクションがあります。出力の最後のセクションは、現在の目的に直接役立ちます。
上記で使用したサンプルプログラムの場合、次のような出力ファイルを取得します
ファイル /.../perl5/lib/perl5//Data/Dump.pm ... (約3,000行) ... ファイル find_unused.pl --> では、このプログラムのファイル サブルーチン(定義) ... 数十行 ... サブルーチン(メイン) パッケージメイン &a_func &43 &cwd &27 サブルーチン a_func パッケージ ? @?? 14 パッケージメイン &鯉 &15 &pp &14
これで、cwd
(27 行目で)が呼び出され、さらに sub でも呼び出されているcarp
ことがわかります。したがって、 およびは使用されません (たとえば、別の方法で見つかったすべてのインポートされたシンボルから)。これは簡単に解析できます。pp
a_func
dd
path
Devel::Symdump
ただし、 whileは使用時に報告されますが、代わりに (従来のコンストラクターとしても)path
使用する場合、この最後のセクションでは報告されず、他の方法も報告されません。new
Path::Tiny
したがって、原則として†</sup> これは、プログラムで使用されていると報告された (関数用の) シンボルを見つける 1 つの方法です。Devel::Symdump
†</sup> ここの例は単純で処理が簡単ですが、インポートされたサブルーチンを使用するためのあらゆる種類の奇妙な方法が考慮されている場合に、どの程度完全であるか、解析が難しいかはわかりません。