On 4/14/20 4:44 PM, Alvaro Herrera wrote: > On 2020-Apr-14, Andrew Dunstan wrote: > >> One of the things that's a bit sad is that perlcritic doesn't generally >> let you apply policies to a given set of files or files matching some >> pattern. It would be nice, for instance, to be able to apply some >> additional standards to strategic library files like PostgresNode.pm, >> TestLib.pm and Catalog.pm. There are good reasons as suggested upthread >> to apply higher standards to library files than to, say, a TAP test >> script. The only easy way I can see to do that would be to have two >> different perlcriticrc files and adjust pgperlcritic to make two runs. >> If people think that's worth it I'll put a little work into it. If not, >> I'll just leave things here. > I think being more strict about it in strategic files (I'd say that's > Catalog.pm plus src/test/perl/*.pm) might be a good idea. Maybe give it > a try and see what comes up. >
OK, in fact those files are in reasonably good shape. I also took a pass through the library files in src/tools/msvc, which had a few more issues. Here's a patch that does the stricter testing for those library files, and fixes them so we get a clean pass This brings to an end my perl gardening project. cheers andrew -- Andrew Dunstan https://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm index dd39a086ce..bd9eac0c80 100644 --- a/src/backend/catalog/Catalog.pm +++ b/src/backend/catalog/Catalog.pm @@ -67,7 +67,7 @@ sub ParseHeader if (!$is_client_code) { # Strip C-style comments. - s;/\*(.|\n)*\*/;;g; + s;/\*(?:.|\n)*\*/;;g; if (m;/\*;) { @@ -260,7 +260,9 @@ sub ParseData # We're treating the input line as a piece of Perl, so we # need to use string eval here. Tell perlcritic we know what # we're doing. - eval '$hash_ref = ' . $_; ## no critic (ProhibitStringyEval) + ## no critic (ProhibitStringyEval) + ## no critic (RequireCheckingReturnValueOfEval) + eval '$hash_ref = ' . $_; if (!ref $hash_ref) { die "$input_file: error parsing line $.:\n$_\n"; diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 1d5450758e..5249053ee2 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -385,7 +385,7 @@ sub set_replication_conf $self->host eq $test_pghost or croak "set_replication_conf only works with the default host"; - open my $hba, '>>', "$pgdata/pg_hba.conf"; + open my $hba, '>>', "$pgdata/pg_hba.conf" || die; print $hba "\n# Allow replication (set up by PostgresNode.pm)\n"; if ($TestLib::windows_os && !$TestLib::use_unix_sockets) { @@ -439,7 +439,7 @@ sub init TestLib::system_or_bail($ENV{PG_REGRESS}, '--config-auth', $pgdata, @{ $params{auth_extra} }); - open my $conf, '>>', "$pgdata/postgresql.conf"; + open my $conf, '>>', "$pgdata/postgresql.conf" || die; print $conf "\n# Added by PostgresNode.pm\n"; print $conf "fsync = off\n"; print $conf "restart_after_crash = off\n"; @@ -1254,7 +1254,7 @@ END $node->clean_node if $exit_code == 0 && TestLib::all_tests_passing(); } - $? = $exit_code; + $? = $exit_code; ## no critic (RequireLocalizedPunctuationVars) } =pod @@ -1462,8 +1462,8 @@ sub psql # https://metacpan.org/pod/release/ETHER/Try-Tiny-0.24/lib/Try/Tiny.pm do { - local $@; - eval { + local $@ = ""; + eval { ## no critic (RequireCheckingReturnValueOfEval) my @ipcrun_opts = (\@psql_params, '<', \$sql); push @ipcrun_opts, '>', $stdout if defined $stdout; push @ipcrun_opts, '2>', $stderr if defined $stderr; @@ -2074,8 +2074,8 @@ sub pg_recvlogical_upto do { - local $@; - eval { + local $@ = ""; + eval { ## no critic (RequireCheckingReturnValueOfEval) IPC::Run::run(\@cmd, ">", \$stdout, "2>", \$stderr, $timeout); $ret = $?; }; diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm index 0e6c4819e4..fd3bbc1979 100644 --- a/src/test/perl/TestLib.pm +++ b/src/test/perl/TestLib.pm @@ -162,6 +162,8 @@ INIT open my $testlog, '>', $test_logfile or die "could not open STDOUT to logfile \"$test_logfile\": $!"; + # don't need to check the result of these dup operations + ## no critic (RequireCheckedOpen) # Hijack STDOUT and STDERR to the log file open(my $orig_stdout, '>&', \*STDOUT); open(my $orig_stderr, '>&', \*STDERR); @@ -409,7 +411,7 @@ Return the full contents of the specified file. sub slurp_file { my ($filename) = @_; - local $/; + local $/ = undef; my $contents; if ($Config{osname} ne 'MSWin32') { diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm index e65ac6fc66..34797d97c3 100644 --- a/src/tools/msvc/Install.pm +++ b/src/tools/msvc/Install.pm @@ -12,9 +12,8 @@ use File::Basename; use File::Copy; use File::Find (); -use Exporter; -our (@ISA, @EXPORT_OK); -@ISA = qw(Exporter); +use Exporter qw(import); +our (@EXPORT_OK); @EXPORT_OK = qw(Install); my $insttype; @@ -45,7 +44,7 @@ sub lcopy sub Install { - $| = 1; + STDOUT->autoflush(1); my $target = shift; $insttype = shift; @@ -56,9 +55,8 @@ sub Install our $config = shift; unless ($config) { - # suppress warning about harmless redeclaration of $config - no warnings 'misc'; + no warnings 'misc'; ## no critic (ProhibitNoWarnings) do "./config_default.pl"; do "./config.pl" if (-f "config.pl"); } @@ -158,7 +156,7 @@ sub Install File::Find::find( { wanted => sub { - /^(.*--.*\.sql|.*\.control)\z/s + /^(?:.*--.*\.sql|.*\.control)\z/s && push(@$pl_extension_files, $File::Find::name); # Don't find files of in-tree temporary installations. diff --git a/src/tools/msvc/MSBuildProject.pm b/src/tools/msvc/MSBuildProject.pm index ebb169e201..aaa3d573ab 100644 --- a/src/tools/msvc/MSBuildProject.pm +++ b/src/tools/msvc/MSBuildProject.pm @@ -1,3 +1,6 @@ + +## no critic (ProhibitMultiplePackages,ProhibitUnusedPrivateSubroutines) + package MSBuildProject; # @@ -11,7 +14,7 @@ use strict; use warnings; use base qw(Project); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub _new { @@ -145,8 +148,11 @@ EOF { confess "Bad format filename '$fileNameWithPath'\n" unless ($fileNameWithPath =~ m!^(.*)/([^/]+)\.(c|cpp|y|l|rc)$!); + # perlcritic is a bit stupid here + ## no critic (ProhibitCaptureWithoutTest) my $dir = $1; my $fileName = $2; + ## use critic if ($fileNameWithPath =~ /\.y$/ or $fileNameWithPath =~ /\.l$/) { push @grammarFiles, $fileNameWithPath; @@ -415,7 +421,7 @@ use strict; use warnings; use base qw(MSBuildProject); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -440,7 +446,7 @@ use strict; use warnings; use base qw(MSBuildProject); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -465,7 +471,7 @@ use strict; use warnings; use base qw(MSBuildProject); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -490,7 +496,7 @@ use strict; use warnings; use base qw(MSBuildProject); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 72a21dbd41..7f67c3582f 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -18,9 +18,8 @@ use Config; use VSObjectFactory; use List::Util qw(first); -use Exporter; -our (@ISA, @EXPORT_OK); -@ISA = qw(Exporter); +use Exporter qw(import); +our (@EXPORT_OK); @EXPORT_OK = qw(Mkvcbuild); my $solution; @@ -106,9 +105,9 @@ sub mkvcbuild sprompt.c strerror.c tar.c thread.c win32env.c win32error.c win32security.c win32setlocale.c); - push(@pgportfiles, 'strtof.c') if ($vsVersion < '14.00'); + push(@pgportfiles, 'strtof.c') if ($vsVersion < 14.00); - if ($vsVersion >= '9.00') + if ($vsVersion >= 9.00) { push(@pgportfiles, 'pg_crc32c_sse42_choose.c'); push(@pgportfiles, 'pg_crc32c_sse42.c'); @@ -212,7 +211,7 @@ sub mkvcbuild $snowball->RelocateFiles( 'src/backend/snowball/libstemmer', sub { - return shift !~ /(dict_snowball.c|win32ver.rc)$/; + return shift !~ /(?:dict_snowball.c|win32ver.rc)$/; }); $snowball->AddIncludeDir('src/include/snowball'); $snowball->AddReference($postgres); @@ -598,6 +597,7 @@ sub mkvcbuild unlink $source_file; open my $o, '>', $source_file || croak "Could not write to $source_file"; + ## no critic (ProhibitHardTabs) print $o ' /* compare to plperl.h */ #define __inline__ __inline @@ -627,6 +627,7 @@ sub mkvcbuild } } '; + ## use critic close $o; # Build $source_file with a given #define, and return a true value @@ -649,8 +650,7 @@ sub mkvcbuild # Some builds exhibit runtime failure through Perl warning # 'Can't spawn "conftest.exe"'; suppress that. - no warnings; - + no warnings; ## no critic (ProhibitNoWarnings) no strict 'subs'; ## no critic (ProhibitNoStrict) # Disable error dialog boxes like we do in the postmaster. diff --git a/src/tools/msvc/Project.pm b/src/tools/msvc/Project.pm index 20f79b382b..c2e82960aa 100644 --- a/src/tools/msvc/Project.pm +++ b/src/tools/msvc/Project.pm @@ -10,7 +10,7 @@ use strict; use warnings; use File::Basename; -sub _new +sub _new ## no critic (ProhibitUnusedPrivateSubroutines) { my ($classname, $name, $type, $solution) = @_; my $good_types = { @@ -278,6 +278,8 @@ sub AddDir my @pieces = split /\s+/, $match; foreach my $fn (@pieces) { + # Deliberately ignore errors from ReplaceFile about files not found + ## no critic (RequireCheckingReturnValueOfEval) if ($top eq "(top_srcdir)") { eval { $self->ReplaceFile($fn, $target) }; diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 545bdcef7b..d9550c3e9e 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -1,3 +1,6 @@ + +## no critic (ProhibitMultiplePackages,ProhibitUnusedPrivateSubroutines) + package Solution; # @@ -10,7 +13,7 @@ use strict; use warnings; use VSObjectFactory; -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub _new { @@ -157,20 +160,22 @@ sub GenerateFiles || confess("Could not open configure.in for reading\n"); while (<$c>) { - if (/^AC_INIT\(\[([^\]]+)\], \[([^\]]+)\], \[([^\]]+)\], \[([^\]]*)\], \[([^\]]+)\]/) + if (/^AC_INIT\(\[([^\]]+)\], \[([^\]]+)\], \[([^\]]+)\], \[(?:[^\]]*)\], \[([^\]]+)\]/) { $ac_init_found = 1; $package_name = $1; $package_version = $2; $package_bugreport = $3; - #$package_tarname = $4; - $package_url = $5; + #$package_tarname = non-capturing-group; + $package_url = $4; if ($package_version !~ /^(\d+)(?:\.(\d+))?/) { confess "Bad format of version: $self->{strver}\n"; } + # perlcritic is a bit stupid here + ## no critic (ProhibitCaptureWithoutTest) $majorver = sprintf("%d", $1); $minorver = sprintf("%d", $2 ? $2 : 0); } @@ -519,7 +524,7 @@ sub GenerateFiles my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion(); # More symbols are needed with OpenSSL 1.1.0 and above. - if ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0') + if ($digit1 >= 1 && $digit2 >= 1 && $digit3 >= 0) { $define{HAVE_ASN1_STRING_GET0_DATA} = 1; $define{HAVE_BIO_GET_DATA} = 1; @@ -931,7 +936,7 @@ sub AddProject # changed their library names from: # - libeay to libcrypto # - ssleay to libssl - if ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0') + if ($digit1 >= 1 && $digit2 >= 1 && $digit3 >= 0) { my $dbgsuffix; my $libsslpath; @@ -1166,7 +1171,7 @@ use strict; use warnings; use base qw(Solution); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -1194,7 +1199,7 @@ use strict; use warnings; use base qw(Solution); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -1222,7 +1227,7 @@ use strict; use warnings; use base qw(Solution); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { @@ -1250,7 +1255,7 @@ use strict; use warnings; use base qw(Solution); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub new { diff --git a/src/tools/msvc/VSObjectFactory.pm b/src/tools/msvc/VSObjectFactory.pm index e6983b241f..dd8cc4952e 100644 --- a/src/tools/msvc/VSObjectFactory.pm +++ b/src/tools/msvc/VSObjectFactory.pm @@ -1,3 +1,6 @@ + +## no critic (ProhibitMultiplePackages) + package VSObjectFactory; # @@ -10,16 +13,15 @@ use Carp; use strict; use warnings; -use Exporter; +use Exporter qw(import); use Project; use Solution; use MSBuildProject; -our (@ISA, @EXPORT); -@ISA = qw(Exporter); +our (@EXPORT); @EXPORT = qw(CreateSolution CreateProject DetermineVisualStudioVersion); -no warnings qw(redefine); ## no critic +no warnings qw(redefine); ## no critic (ProhibitNoWarnings) sub CreateSolution { diff --git a/src/tools/perlcheck/perlcriticrc b/src/tools/perlcheck/perlcriticrc index e230111b23..27b4af1892 100644 --- a/src/tools/perlcheck/perlcriticrc +++ b/src/tools/perlcheck/perlcriticrc @@ -22,3 +22,30 @@ verbose = %f: %m at line %l, column %c. %e. ([%p] Severity: %s)\n # insist on use of the warnings pragma [TestingAndDebugging::RequireUseWarnings] severity = 5 + + +# sev 4 +[-Modules::ProhibitAutomaticExportation] +[-InputOutput::RequireBriefOpen] +[-Subroutines::RequireArgUnpacking] +[Variables::RequireLocalizedPunctuationVars] +allow = %ENV %SIG +[-Objects::ProhibitIndirectSyntax] +[TestingAndDebugging::ProhibitProlongedStrictureOverride] +statements = 10 +[-BuiltinFunctions::RequireBlockGrep] +[TestingAndDebugging::ProhibitNoWarnings] +allow = once + +# sev 3 +[-ErrorHandling::RequireCarping] +[-RegularExpressions::RequireExtendedFormatting] +[-Variables::ProhibitPackageVars] +[-ControlStructures::ProhibitCascadingIfElse] +[-Subroutines::ProhibitExcessComplexity] +[-ValuesAndExpressions::ProhibitImplicitNewlines] +[-Subroutines::ProhibitManyArgs] +[-InputOutput::ProhibitBacktickOperators] +[-BuiltinFunctions::ProhibitLvalueSubstr] +[-ValuesAndExpressions::RequireQuotedHeredocTerminator] +[-RegularExpressions::ProhibitComplexRegexes] diff --git a/src/tools/perlcheck/pgperlcritic b/src/tools/perlcheck/pgperlcritic index 1c2f787580..08edd86427 100755 --- a/src/tools/perlcheck/pgperlcritic +++ b/src/tools/perlcheck/pgperlcritic @@ -14,7 +14,21 @@ PERLCRITIC=${PERLCRITIC:-perlcritic} . src/tools/perlcheck/find_perl_files -find_perl_files | xargs $PERLCRITIC \ +flist=`mktemp` +find_perl_files > $flist + +pattern='src/test/perl/|src/backend/catalog/Catalog.pm|src/tools/msvc/[^/]*.pm' + +# normal sev 5 critic +egrep -v "$pattern" < $flist | xargs $PERLCRITIC \ --quiet \ --program-extensions .pl \ --profile=src/tools/perlcheck/perlcriticrc + +# more strict sev 3 critic for some library files +egrep "$pattern" < $flist | xargs $PERLCRITIC --severity 3 \ + --quiet \ + --program-extensions .pl \ + --profile=src/tools/perlcheck/perlcriticrc + +rm -f $flist