2012-12-03 64 views
11

我們在這裏一直在使用Perl::Critic來強制執行我們的代碼約定。最近我們遇到了/tmp目錄由於Temp::File::tempdir函數而被填滿的問題。 tempdir在Perl進程終止時清除,但由於我們的整個後端是一個Perl進程,所以只有當服務器本身重新啓動時(不是很常見),纔會發生這種情況。我們希望鼓勵開發人員在將來使用newdir對象方法,一旦對象超出範圍,它就會自行清理。Perl :: Critic「不要使用這種方法」 - 類型規則

基本上,我們試圖將Temp::File::tempdir標記爲違反代碼慣例,但我似乎無法找到任何在CPAN上會類似的規則。我明白,在不引入誤報的情況下,這很難在動態類型語言中實施,但我希望有人在過去遇到過類似的問題,並使用了另一個棄用的函數。我們並不期望抓住所有棘手的情況,只有Temp::File::tempdir最明顯的用途。當newdir可以完成這項工作時,不要想方設法騙過批評者(開發者總是可以使用## no critic),這樣做的目的是阻止tempdir的意外使用。如果定義了use Temp::File(最好檢查沒有其他重新定義tempdir),並且使用Temp::File::tempdir時,使用tempdir時可能已足夠。

有沒有類似的東西,還是我應該從頭開始?謝謝

+2

好奇此輸出。有可配置的'ProhibitEvilModules'和'ProhibitEvilVariables'策略,但沒有'ProhibitEvilMethods'? – mob

回答

9

Perl::Critic目前沒有任何東西可以提供您需要的東西,但很可能會添加一項策略來執行類似操作。不幸的是,PPI不夠全面,無法正確識別程序中每個令牌的做法,因此它需要更多的編碼。

這爲use File::Temp聲明程序檢查,嘗試使用任何

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

(與任何分隔符爲qqqqw形式)導入tempdir。它還會檢查看起來像函數調用的PPI::Token::Word節點,該節點等於File::Temp::tempdir

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; 

與此代碼

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; 

生成從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'分類器非常含糊,僅僅意味着這個裸詞似乎不是它檢查的其他九種可能性中的任何一種。 – Borodin

相關問題