NAME
Perl::Critic::Policy::Generic::External - Dynamically ingest violations from external files, Copilot, ChatGPT, Claude
DESCRIPTION
Perl::Critic is already used by organizations to analyze and track code improvement needs. External tooling that performs static analysis of code can be integrated into the same workflows by producing data that is directly available when Perl::Critic analyzes each file.
Example
Suppose an external scanner identifies the following concerns and categorizes them as:
# Description for BuiltinFunctions::UseSay: Use 'say' instead of print \n.
# Explanation for BuiltinFunctions::UseSay: ... so using 'say' is more common.
a.pl 3 0 BuiltinFunctions UseSay
a.pl 3 6 BuiltinFunctions UseSprintf
When Generic::External is configured to use that source file, it yields:
perlcritic --verbose '%m in %f %l:%c (%p)\n' a.pl
Use 'say' instead of print \n in a.pl 3:1 (BuiltinFunctions::UseSay)
UseSprintf in a.pl 3:6 (BuiltinFunctions::UseSprintf)
CONFIGURATION
filetsv
A tab-separated file can be used to identify files with violations:
[Generic::External]
filetsv = filename.tsv
The general format of the file should be tab separated columns:
source line column Category Policy
The violations can appear in any order. Note that the file may be scanned multiple times during perlcritic execution.
Descriptions and Explanations may be included in the file:
# Description for Category::Policy: Here is some description.
# Explanation for Category::Policy: Here is some explanation.
Each is limited to a single line and the category and policy must exactly match the resulting violation package name.
VIOLATIONS
Category and Policy
Each violation must include a Category and Policy, which will associate with a violation for Perl::Critic::Policy::Category::Policy. Names must match /[A-Za-z][A-Za-z0-9_]*/ as with regular Perl package names. Names are first stripped of all extra characters so "Some Category" will become "SomeCategory".
Filenames
At this time, filenames must match exactly. Any file that perlcritic scans of the form ./source.ext will check external references only for source.ext.
Violation location
Violations will generally emit based on the line and column as:
* Exactly at the matching token if it exists within the document.
* With this token if the next token would be past the violation.
If a violation has a column number of zero, it will emit with the first token on that line.
TODO
The following appear in no particular priority order.
filetsv
Subject to change... Currently the file is scanned when each source file is checked by perlcritic. To reduce unnecessary reads, the full file list is loaded on first read; any document being scanned by Perl::Critic will be skipped if the filename didn't appear in the file. Otherwise the file will be fully read for matching lines. This approach is primarily to avoid the memory overhead of fully loading the file in the first pass, since large repositories may have 10--100MB of violations per 1000 files. Options include loading it and not caring, always rereading, or setting some configurable limit at which rereading is enabled.
Input
Add support for: filejson, cli.
After the performance/memory question has been answered for filetsv, it may be reasonable to support wildcard directories/names as input.
Policy skipping
It may be reasonable to skip any external policies that are already loaded/defined by the Perl::Critic profile. Presumably those represent overlaps and should not be emitted twice.
BUGS
None known.