2009-08-27 8 views
5

これは重複している場合、私の謝罪します。私は検索するための適切な用語を知らないかもしれません。Perlモジュールファイルからすべての変数、モジュール、関数名を抽出するツールはありますか?

私は、より大きなアプリケーションの断片であるPerlモジュールファイル(.pm)を分析することを任されています。コード、変数名、モジュール名、関数呼び出しをすべて取り出すツール、アプリ、スクリプトはありますか?さらに、このファイル内で宣言されているのか、それとも外部のものであるのかを特定するものになります。

このようなツールはありますか?私は1つのファイルしか取得しないので、これは実行可能なものではありません。

+4

はこちらをご覧ください: http://stackoverflow.com/questions/607282/whats-the-best-way-to-discover-all-subroutines-a-perl-module-has をいくつかの方法が述べられています。 –

答えて

9

新しくよくお勧めするClass::Sniffをご覧ください。ドキュメントから

use Class::Sniff; 
my $sniff = Class::Sniff->new({class => 'Some::class'}); 

my $num_methods = $sniff->methods; 
my $num_classes = $sniff->classes; 
my @methods  = $sniff->methods; 
my @classes  = $sniff->classes; 

{ 
    my $graph = $sniff->graph; # Graph::Easy 
    my $graphviz = $graph->as_graphviz(); 

    open my $DOT, '|dot -Tpng -o graph.png' or die("Cannot open pipe to dot: $!"); 
    print $DOT $graphviz; 
} 

print $sniff->to_string; 
my @unreachable = $sniff->unreachable; 
foreach my $method (@unreachable) { 
    print "$method\n"; 
} 

これは、あなたが道のほとんどを取得します。一部のvariablesは、範囲によっては利用できない場合があります。

+0

+1私は最速の銃賞に殴られたように見え、より良い答えを得ました。私のCPAN知識の欠如を呪います! –

+1

私は数ヶ月前にそれを聞いたので私が知っている理由があります:) –

+0

これはファイル上で動作しますか?問題のモジュール(解析しなければならないモジュール)は、そのコードを持っていないので、私が満足できない依存関係があります。 – romandas

2

この質問にはより良い回答がありますが、投稿されていないので、私は西で最も速い銃を要求し、先に進んで「クイックフィックス」を投稿します。

このようなツールは、実際には存在し、Perlに組み込まれています。特殊なハッシュ変数を使用して、任意の名前空間のシンボルテーブルにアクセスできます。 main名前空間(デフォルト1)にアクセスするには:あなたのパッケージがマイ/ Package.pmという名前、および名前空間My::Packageでこれですされている場合は

for(keys %main::) { # alternatively %:: 
    print "$_\n"; 
} 

、あなたは同じ効果を達成するために%My::Package::から%main::を変更します。シンボルテーブルのperldoc perlmodのエントリを参照してください。彼らはそれを説明し、より良いかもしれない、または少なくともあなたが仕事のための適切なモジュールを見つけるのを開始するいくつかの選択肢を列挙します(これはPerlのモットーです。それ)。利用可能

+0

これを使用するためにモジュールをロードする必要はありませんか? – romandas

+0

モジュールをロードせずにこれをやりたければ、昔ながらの 'grep'を使わなければならないでしょう。 Perlのregexesを使って、数多くの改良された機能を持っているPerlの 'grep'の大幅な拡張です。 –

+0

'%main ::'はパッケージ変数のみを持ち、字句変数( 'my'で作成されたもの)はそこに格納されません。 –

7

もう一つのCPANツールは、これは、クラス::スニフにあなたに似た結果が得られますClass::Inspector

use Class::Inspector; 

# Is a class installed and/or loaded 
Class::Inspector->installed('Foo::Class'); 
Class::Inspector->loaded('Foo::Class'); 

# Filename related information 
Class::Inspector->filename('Foo::Class'); 
Class::Inspector->resolved_filename('Foo::Class'); 

# Get subroutine related information 
Class::Inspector->functions('Foo::Class'); 
Class::Inspector->function_refs('Foo::Class'); 
Class::Inspector->function_exists('Foo::Class', 'bar'); 
Class::Inspector->methods('Foo::Class', 'full', 'public'); 

# Find all loaded subclasses or something 
Class::Inspector->subclasses('Foo::Class'); 

です。あなたはまだ自分でいくつかの処理をしなければならないかもしれません。

8

私が正しく理解していれば、Perlのソースコードを調べるツールを探しています。私はPPIを提案するつもりです。

 ... 
    'new', 
    'new', 
    'new', 
    'output', 
    'new', 
    'new', 
    'new', 
    'new', 
    'new', 
    ... 

複数のクラスをHTML/Template.pmで定義されているので、この意志の出力は、

#!/usr/bin/perl 

use strict; 
use warnings; 

use PPI::Document; 
use HTML::Template; 

my $Module = PPI::Document->new($INC{'HTML/Template.pm'}); 

my $sub_nodes = $Module->find(
    sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name } 
); 

my @sub_names = map { $_->name } @$sub_nodes; 

use Data::Dumper; 
print Dumper \@sub_names; 

注:ここ

はドキュメントからアップ石畳の一例です。明らかに、あまり単純ではないアプローチは、階層的な方法でPDOMツリーで動作します。

3

解析しているコードを実行せずに実行したい場合は、PPIでこれを行うのはかなり簡単です。私のModule::Use::Extractをチェックしてください。これは短いコードで、PPIのPerlDOMから必要な要素を抽出する方法を示しています。

すでにコンパイルしたコードでやりたいのであれば、答えの中の他の提案が良いでしょう。

0

私はこのcolumnでRandal Schwartzが探していたものにかなり良い答えが見つかりました。彼は私が探していた情報を正確に抽出するためにB :: Xrefモジュールを使って実演しました。彼がモジュールのファイル名で使った評価済みの1行を置き換えるだけで、チャンピオンのように働きました。明らかにB :: XrefにはActiveState Perlが付属しているので、追加のモジュールは必要ありませんでした。

perl -MO=Xref module.pm 
関連する問題