2012-12-03 10 views
11

私たちは、コードの規則を施行するために仕事でここにPerl::Criticを使用してきました。最近、Temp::File::tempdir機能のために/tmpディレクトリがいっぱいになるという問題が発生しました。 tempdirはPerlプロセスが終了するとクリーンアップされますが、バックエンド全体がPerlプロセスなので、これはサーバー自体が再起動したときにのみ発生します(あまり頻繁ではありません)。私たちは開発者が将来オブジェクトメソッドnewdirを使用することを奨励したいと考えています。オブジェクトメソッドは、オブジェクトが有効範囲外になるとすぐにクリーンアップします。のPerl ::評論家「このメソッドを使用しないでください」型のルール

基本的には、コード規約違反としてTemp::File::tempdirをマークしようとしていますが、CPANで似たようなルールは見つけられません。私は、誤った評価を導入することなく、動的に型付けされた言語でこれを実行することは難しいと理解していますが、他の非難された関数を使って過去に同様の問題に遭遇したと思います。私たちはすべてのトリッキーなケースを捕まえることを期待していませんが、Temp::File::tempdirの最も明白な用途だけです。アイデアは評論家をだますための試みをすべて(開発者は常にちょうど## no criticを使用することができます)をキャッチしていない、newdirは仕事をすることができるときtempdirを誤って使用することを阻止するためです。おそらくuse Temp::Fileが定義されている場合(好ましくは他に何もtempdirを再定義していないことを確認)とTemp::File::tempdirを使用する場合tempdirを使用する場合に文句を言うには十分だろう。

はすでに似たものがある、または私はゼロからスタートする必要がありますか?おかげ

+2

からこの出力を生成します。設定可能な 'ProhibitEvilModules'と' ProhibitEvilVariables'ポリシーはありますが、 'ProhibitEvilMethods'ポリシーはありませんか? – mob

答えて

9

はあなたが必要なものを提供することが本でPerl::Criticには何もありませんが、それはそれのように何かをするポリシーを追加、かなり可能です。残念ながら、は、プログラムの各トークンが何をしているのかを正しく識別するのに十分な包括的ではないので、それ以上のコーディングが必要です。

qqq、及びqwフォームの任意の区切り文字で)

use File::Temp 'tempdir'; 
use File::Temp q(tempdir); 
use File::Temp "tempdir"; 
use File::Temp qq(tempdir); 
use File::Temp qw/ tempdir /; 

のいずれかを使用してtempdirをインポートしようとuse File::Tempステートメントのためのこのプログラムをチェックします。また、関数呼び出しのようになり、File::Temp::tempdirに等しいPPI::Token::Wordノードをチェックします。このコード

use strict; 
use warnings; 

use File::Temp 'tempdir'; 
use File::Temp "tempdir"; 
use File::Temp qw/ tempdir /; 

my $dir = tempdir(); 
$dir = tempdir; 
$dir = File::Temp::tempdir; 

my $ft = File::Temp->new; 
$dir = $ft->newdir; 

package Perl::Critic::Policy::Prohibit_tempdir; 

use strict; 
use warnings; 

use Perl::Critic::Utils qw{ is_function_call :severities }; 
use Scalar::Util 'blessed'; 

use base 'Perl::Critic::Policy'; 

my $DESC = 'Temp::File::tempdir function'; 
my $EXPL = 'The tempdir function from Temp::File is deprecated. Use newdir method instead'; 

sub default_severity { $SEVERITY_HIGH }; 

sub applies_to{ qw/ PPI::Statement::Include PPI::Token::Word/} 

sub violates { 

    my ($self, $elem) = @_; 

    if ($elem->isa('PPI::Statement::Include')) { 

    return unless $elem->type eq 'use'; 

    my $module = $elem->module; 
    return unless $module and $module eq 'File::Temp'; 

    for my $kid ($elem->children) { 

     next unless blessed($kid) =~ /^PPI::Token::Quote/; 

     if ($kid->can('string') and $kid->string eq 'tempdir' 
      or $kid->can('literal') and grep $_ eq 'tempdir', $kid->literal) { 
     return $self->violation($DESC, $EXPL, $elem); 
     } 
    } 
    } 
    else { 
    if (is_function_call($elem) and $elem eq 'File::Temp::tempdir') { 
     return $self->violation($DESC, $EXPL, $elem); 
    } 
    } 

    return; 
} 

1; 

は、好奇心が強いperlcritic -4 test.pl

Code not contained in explicit package at line 1, column 1. Violates encapsulation. (Severity: 4) 
Temp::File::tempdir function at line 4, column 1. The tempdir function from Temp::File is deprecated. Use newdir method instead. (Severity: 4) 
Temp::File::tempdir function at line 5, column 1. The tempdir function from Temp::File is deprecated. Use newdir method instead. (Severity: 4) 
Temp::File::tempdir function at line 6, column 1. The tempdir function from Temp::File is deprecated. Use newdir method instead. (Severity: 4) 
Temp::File::tempdir function at line 10, column 8. The tempdir function from Temp::File is deprecated. Use newdir method instead. (Severity: 4) 
Module does not end with "1;" at line 13, column 1. Must end with a recognizable true value. (Severity: 4) 
+0

おかげで、これは我々が必要とするほぼ正確に何を行い、それがまだ線8と9をキャッチしていませんが、私はそうするためにそれを微調整し、おそらくそれは、より汎用的にするような方法は、それにするモジュールごとに指定することができますより一般的なビット。 –

+0

質問に記載した方法を使用しました。 8行目や9行目などの呼び出しは、先行する行4,5,6のインスタンスがある場合にのみコンパイルされます。つまり、呼び出す前にサブルーチンをインポートする必要があります。モジュール名で完全修飾されていない 'tempdir'への呼び出しを特定することの問題は、' PPI'がベアワードの外観の文脈についてあまり役に立たないということです。 'Perl :: Critic :: Utils'によって提供される' is_function_call'クラシファイアは非常にあいまいであり、単にベアワードがチェックする他の9つの可能性のいずれかであるとは限りません。 – Borodin

関連する問題