2012-12-03 18 views
11

Chúng tôi đã sử dụng Perl::Critic tại nơi làm việc để thực thi các quy ước về mã của chúng tôi. Gần đây, chúng tôi đã gặp sự cố với thư mục /tmp được lấp đầy do chức năng Temp::File::tempdir. tempdir dọn dẹp khi quá trình Perl chấm dứt, nhưng vì toàn bộ chương trình phụ trợ của chúng tôi là một quá trình Perl, điều này chỉ xảy ra khi máy chủ tự khởi động lại (không thường xuyên). Chúng tôi muốn khuyến khích các nhà phát triển sử dụng phương pháp đối tượng newdir trong tương lai, làm sạch sau khi chính nó ngay khi đối tượng nằm ngoài phạm vi.Perl :: Phê bình "Không sử dụng phương pháp này" quy tắc loại

Về cơ bản, chúng tôi đang cố gắng đánh dấu Temp::File::tempdir là vi phạm quy ước về mã, nhưng dường như tôi không thể tìm thấy bất kỳ quy tắc nào tương tự trên CPAN. Tôi hiểu rằng điều này khó thực thi bằng ngôn ngữ được nhập động mà không đưa ra các mặt tích cực sai, nhưng tôi hy vọng một người nào đó đã gặp sự cố tương tự trong quá khứ với một chức năng không được chấp nhận khác. Chúng tôi không mong đợi để nắm bắt tất cả các trường hợp khó khăn hoặc, chỉ sử dụng rõ ràng nhất của Temp::File::tempdir. Ý tưởng là để khuyến khích sử dụng tình cờ tempdir khi newdir có thể thực hiện công việc, không phải để nắm bắt mọi nỗ lực để đánh lừa nhà phê bình (nhà phát triển luôn có thể sử dụng ## no critic). Nó có thể sẽ đủ để khiếu nại khi tempdir được sử dụng nếu use Temp::File được xác định (tốt nhất là kiểm tra xem không có gì khác xác định lại tempdir) và khi sử dụng Temp::File::tempdir.

Đã có điều gì đó tương tự hay tôi nên bắt đầu từ đầu? Cảm ơn

+2

Tò mò. Có các chính sách 'ProhibitEvilModules' và' ProhibitEvilVariables' có thể cấu hình, nhưng không có 'ProhibitEvilMethods'? – mob

Trả lời

9

Hiện tại, không có bất kỳ điều gì trong số Perl::Critic để cung cấp những gì bạn cần nhưng có thể thêm chính sách để thực hiện một việc như vậy. Thật không may là PPI không đủ để xác định đúng từng mã thông báo trong chương trình đang hoạt động, vì vậy nó cần mã hóa nhiều hơn nó có thể.

chương trình này kiểm tra cho một tuyên bố use File::Temp mà cố gắng để nhập tempdir sử dụng bất kỳ

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

(với bất kỳ delimiter cho q, qq, và qw mẫu đính kèm). Nó cũng kiểm tra một nút PPI::Token::Word trông giống như một cuộc gọi hàm và bằng 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; 

với mã này

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; 

tạo ra sản lượng này từ 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

Cảm ơn, điều này gần như chính xác những gì chúng ta cần, nó không bắt dòng 8 và 9, nhưng tôi sẽ tinh chỉnh nó để làm như vậy, và có thể làm cho nó chung chung hơn để các phương thức có thể được chỉ định cho mỗi mô-đun để làm cho nó trở thành bit chung chung hơn. –

+0

Tôi đã sử dụng cách tiếp cận mà bạn mô tả trong câu hỏi của mình. Các cuộc gọi như trong dòng 8 và 9 sẽ chỉ biên dịch nếu có trường hợp trước đó của dòng 4, 5 hoặc 6. tức là chương trình con phải được nhập trước khi nó có thể được gọi. Vấn đề với việc xác định các cuộc gọi đến 'tempdir' không đủ điều kiện với tên mô-đun là 'PPI' không phải là rất hữu ích về ngữ cảnh của sự xuất hiện của người chủ quán. Trình phân loại 'is_function_call' được cung cấp bởi' Perl :: Critic :: Utils' rất mơ hồ, và đơn giản có nghĩa là thanh chắn không xuất hiện là bất kỳ một trong chín khả năng khác mà nó kiểm tra. – Borodin

Các vấn đề liên quan