diff --git a/README.md b/README.md index 8b9543b..2864255 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,18 @@ You can use $workspaceFolder in includePaths which will be replaced by the full ### Perl Critic Customization -You should specify a Perl::Critic profile via `perlnavigator.perlcriticProfile`. You can use `$workspaceFolder` as a place holder here. If perlcriticProfile is not set, it will check for `~./perlcriticrc`. -If that also does not exist, a default profile will be used. This default profile is not very strict. -The default severities are reasonable, (primarily used for coloring the squiggly underlines) but you can change `perlnavigator.severity1` through severity5. Allowable options are error, warning, info, and hint. +You should specify a Perl::Critic profile via `perlnavigator.perlcriticProfile`. +You can use `$workspaceFolder` as a place holder here. +If perlcriticProfile is not set, it will use the same logic to find profiles as [Perl::Critic](https://metacpan.org/pod/Perl::Critic#CONFIGURATION). +If none exist, a [default profile](server/src/perl/defaultCriticProfile) will be used. +This default profile is not very strict, but is at least consistent unlike the default behavior of Perl::Critic (load *all* installed policy modules). +The default severities are reasonable, (primarily used for coloring the squiggly underlines) but you can change `perlnavigator.severity1` through severity5. +Allowable options are error, warning, info, and hint. ### Perl Tidy Customization -It is recommended to set `perlnavigator.perltidyProfile` if you would like customized formatting. Otherwise, the default settings will be used. I might create a default profile at some point. +It is recommended to set `perlnavigator.perltidyProfile` if you would like customized formatting. +Otherwise, the default profile discovery logic in [Perl::Tidy](https://metacpan.org/dist/Perl-Tidy/view/bin/perltidy#The-perltidyrc-file) will be used. +I might create a default profile at some point. ### Perlimports Customization Perlimports offers additional diagnostics when imports can be cleaned up. When perlimports is enabled, "Format Document" and "Format Selection" will run perlimports in addition to perltidy. @@ -96,6 +102,7 @@ Sublime Text requires the following minimum settings under LSP settings (modify "settings": { // "perlnavigator.perltidyProfile": "~/.perltidyrc", // "perlnavigator.perlcriticProfile": "~/.perlcriticrc", + # In which case you probably deserve the default behavior of Perl::Critic. // "perlnavigator.perlcriticMessageFormat": "%m - %e", // "perlnavigator.perlEnvAdd": false, // default: true // "perlnavigator.perlEnv": { diff --git a/server/src/perl/criticWrapper.pl b/server/src/perl/criticWrapper.pl index abf70f2..92ed639 100644 --- a/server/src/perl/criticWrapper.pl +++ b/server/src/perl/criticWrapper.pl @@ -1,6 +1,7 @@ use strict; use warnings; use Getopt::Long qw( GetOptions ); +use Cwd(); use File::Spec (); use File::Basename (); use utf8; @@ -104,24 +105,32 @@ sub AsciiReplacementChar { return $ord < 26 ? chr($ord + 65) : chr($ord + 71); } +# Search for critic policy. +# Follow the same convention as the upstream tool: https://metacpan.org/pod/Perl::Critic#CONFIGURATION +# Opts > Env > cwd > home > default +# You may be asking yourself, why do any of this at all versus the simplicity of the tidy wrapper? +# Perltidy follows the same logic to resolve RC files, after all. +# Because we want to provide a default configuration file, which means we have to substantially reimplement logic in Perl::Critic::UserProfile. +# This is because the default behavior of Perl::Critic is to load all available policies installed, which leads to inconsistent behavior. sub resolve_profile { my $profile = shift; - if ($profile){ - return $profile if -f $profile; - die("User specified Critic profile $profile not readable"); - } - - return $ENV{'PERLCRITIC'} if $ENV{'PERLCRITIC'} && -r $ENV{'PERLCRITIC'}; - if ( my $home_dir = find_home_dir() ) { - $profile = File::Spec->catfile( $home_dir, '.perlcriticrc' ); - return $profile if -f $profile; + my @possible_rc = ( + $profile, + $ENV{'PERLCRITIC'}, + File::Spec->catfile( Cwd::getcwd(), '.perlcriticrc' ), + File::Spec->catfile( find_home_dir(), '.perlcriticrc' ), + File::Spec->catfile( File::Basename::dirname(__FILE__), 'defaultCriticProfile' ), + ); + + foreach my $rc (@possible_rc) { + # It is not necessary and indeed would be a TOCTOU to die because of a file test here. + # Perl::Critic::UserProfile will die if it cant't parse via Config::Tiny. + return $rc if $rc && -f $rc; } - $profile = File::Spec->catfile( File::Basename::dirname(__FILE__), 'defaultCriticProfile' ); - die("Can't find Navigator's default profile $profile ?!") unless( -f $profile ); - - return $profile; + # If nothing above exists, go with the default behavior. + return; } sub find_home_dir {