6

これが重複している場合は、お詫び申し上げます。検索する適切な用語がわからない場合があります。

私は、より大きなアプリケーションのフラグメントであるPerlモジュールファイル(.pm)を分析する任務を負っています。コードを調べて、すべての変数名、モジュール名、関数呼び出しを引き出すツール、アプリ、またはスクリプトはありますか?さらに良いのは、それがこのファイル内で宣言されているのか、それとも外部のものであるのかを識別するものです。

そのようなツールは存在しますか?取得するファイルは1つだけなので、これは実行できるものではありません。基本的な静的分析だけだと思います。

4

6 に答える 6

10

新しいが、よくお勧めし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範囲によっては、ご利用いただけない場合があります。

于 2009-08-27T20:56:13.213 に答える
8

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

これは、ドキュメントからまとめた例です。

#!/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;

これは次のように出力されることに注意してください。

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

複数のクラスがで定義されているためHTML/Template.pmです。明らかに、それほど単純ではないアプローチは、階層的な方法でPDOMツリーを処理します。

于 2009-08-27T21:33:25.570 に答える
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' );

これにより、Class::Sniffと同様の結果が得られます。あなたはまだあなた自身でいくつかの処理をしなければならないかもしれません。

于 2009-08-27T21:02:41.700 に答える
3

この質問に対するより良い答えがありますが、それらは投稿されていないので、私は西部で最速の銃を主張し、先に進んで「クイックフィックス」を投稿します。

このようなツールは実際に存在し、Perlに組み込まれています。特別なハッシュ変数を使用して、任意の名前空間のシンボルテーブルにアクセスできます。main名前空間(デフォルトの名前空間)にアクセスするには:

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

パッケージの名前がMy/Package.pmであり、名前空間My::Packageにある場合は、に変更%main::%My::Package::て同じ効果を実現します。シンボルテーブルのperldocperlmodエントリを参照してください-それらはそれを説明し、より良いかもしれないいくつかの選択肢をリストします、または少なくともあなたが仕事に適切なモジュールを見つけることを始めます(それはPerlのモットーです-1つ以上のモジュールがありますやれ)。

于 2009-08-27T20:57:53.647 に答える
3

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

すでにコンパイルしたコードでそれを実行したい場合は、回答の他の提案の方が適しています。

于 2009-08-28T19:17:56.807 に答える
1

ランダル・シュワルツのこのコラムで私が探していたものに対するかなり良い答えを見つけました。彼は、B :: Xrefモジュールを使用して、私が探していた情報を正確に抽出する方法を示しました。彼が使用した評価済みのワンライナーをモジュールのファイル名に置き換えるだけで、チャンピオンのように機能し、B ::XrefにはActiveStatePerlが付属しているため、追加のモジュールは必要ありませんでした。

perl -MO=Xref module.pm 
于 2009-08-28T20:44:21.597 に答える