11

我们一直Perl::Critic在工作中使用这里来执行我们的代码约定。最近我们遇到/tmp了由于该Temp::File::tempdir功能而导致目录被填满的问题。tempdir当 Perl 进程终止时进行清理,但由于我们的整个后端是一个 Perl 进程,所以这只发生在服务器本身重新启动时(不经常)。我们希望鼓励开发人员newdir在未来使用对象方法,一旦对象超出范围,该方法就会自行清理。

基本上,我们试图将其标记Temp::File::tempdir为违反代码约定,但我似乎无法在 CPAN 上找到任何类似的规则。我知道在不引入误报的情况下很难在动态类型的语言中强制执行,但我希望过去有人遇到过类似的问题,而另一个已弃用的函数。我们也不指望能捕捉到所有棘手的情况,只希望捕捉到Temp::File::tempdir. 这个想法是为了阻止意外使用tempdirwhen newdircould 做这项工作,而不是抓住所有试图愚弄评论家的企图(开发人员总是可以只使用## no critic)。tempdir如果use Temp::File已定义(最好检查没有其他东西重新定义tempdir)以及何时使用,抱怨何时使用可能就足够了Temp::File::tempdir

是否已经有类似的东西,或者我应该从头开始?谢谢

4

1 回答 1

9

目前没有任何东西Perl::Critic可以提供你需要的东西,但是很可能添加一个策略来做类似的事情。不幸PPI的是,它还不够全面,无法正确识别程序中的每个令牌在做什么,因此它需要比它可能的更多编码。

该程序检查use File::Temp尝试tempdir使用任何导入的语句

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

q(带有、qqqw形式的任何分隔符)。它还检查一个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)
于 2012-12-04T06:41:58.270 回答