Perl:: Критик правило "Не используйте этот метод"

Мы использовали Perl::Critic здесь, на работе, чтобы обеспечить соблюдение наших соглашений кода. Недавно мы столкнулись с проблемами /tmp каталог заполняется из-за Temp::File::tempdir функция. tempdir очищается, когда завершается процесс Perl, но поскольку весь наш бэкэнд представляет собой процесс Perl, это происходит только тогда, когда сам сервер перезапускается (не очень часто). Мы хотим призвать разработчиков использовать newdir метод объекта в будущем, который убирает за собой, как только объект выходит из области видимости.

По сути, мы пытаемся отметить Temp::File::tempdir как нарушение соглашения о коде, но я не могу найти какое-либо правило, которое было бы похоже на CPAN. Я понимаю, что это трудно реализовать на языке с динамической типизацией без введения ложных срабатываний, но я ожидаю, что кто-то сталкивался с подобной проблемой в прошлом с другой устаревшей функцией. Мы не ожидаем отловить все сложные случаи, только самые очевидные случаи использования Temp::File::tempdir, Идея состоит в том, чтобы препятствовать случайному использованию tempdir когда newdir может сделать работу, чтобы не уловить все попытки обмануть критика (разработчик всегда мог просто использовать ## no critic). Вероятно, было бы достаточно, чтобы жаловаться, когда tempdir используется, если use Temp::File определяется (желательно проверять, что ничего не переопределяет tempdir) и когда Temp::File::tempdir используется.

Уже есть что-то подобное, или я должен начать с нуля? Спасибо

1 ответ

Решение

Там нет ничего в 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, qq, а также qw формы). Он также проверяет наличие 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)
Другие вопросы по тегам