読者です 読者をやめる 読者になる 読者になる

PPIとTest::LocalFunctions、Compiler::Lexer周辺について調べたこと

帰省中にTwitterを眺めていたら話題になっていて、知らなかった事だったので調べてみました。

MANIFESTファイルとMANIFEST.SKIPファイル

MANIFESTファイルは、パッケージに含めるファイルの一覧です。
MANIFEST.SKIPファイルには、パッケージに含めたくないファイルの一覧です。

ExtUtils::Manifest

ExtUtils::manifestは、MANIFESTファイルを書いたりチェックしたりするためのツールです。

use ExtUtils::Manifest qw(skipcheck maniread);
use Data::Dumper;

# MANIFEST.SKIPファイルの指定によりスキップされるファイルチェック
warn skipcheck();

# MANIFESTファイルに記述されているリストを読み込む
warn Dumper maniread();

PPI

PPIは、Pure PerlPerlスクリプトの構造を解析することを目的としたプロジェクトです。

use PPI::Document;
use PPI::Dumper;

my $filename = $ARGV[0];

my $doc = PPI::Document->new( $filename );
my $dumper = PPI::Dumper->new($doc);
warn $dumper->string();


以下の様なモジュールに使われているそうです。

Test::LocalFunctions

Test::LocalFunctionsは、MANIFESTファイルに記述されているモジュールを対象に、使われていないローカル関数を検出するモジュールです。
内部ではPPIが使われています(Bで再実装するかもということです)。

use Test::LocalFunctions;

all_local_functions_ok();

Compiler::Lexer

Compiler::Lexerは、Perlの字句解析器モジュールです。C++で実装されており、高速に動くようです。

use Compiler::Lexer;
use Data::Dumper;

# 解析対象のperlスクリプトファイル名を読み込む
my $filename = $ARGV[0];

# スクリプト内容を読み込む
open my $fh, $filename or die "Error";
my $code = do { local $/; <$fh> };

# 解析器を生成
my $lexer = Compiler::Lexer->new($filename);

# トークン化
my $tokens = $lexer->tokenize($code);
print Dumper $tokens;

# シンタックスのレベル単位でグループ化
print Dumper $lexer->get_groups_by_syntax_level($tokens, Compiler::Lexer::SyntaxType::T_Stmt);

# 使用しているモジュール・プラグマの一覧
print Dumper $lexer->get_used_modules($code);

現在は、
mixiのコピペ検出ツールで使われていたり、
続・技術的負債の把握と改善を促すために - mixi Engineers' Blog

PPIで書かれていたモジュールが、Compiler::Lexerで再実装されたりしています。